From efcaffba43ae0c4ad69e6f9cb190df43db57d70c Mon Sep 17 00:00:00 2001 From: Esco Date: Thu, 25 Apr 2024 13:49:18 +0200 Subject: [PATCH 01/92] Added Places --- src/_nav.jsx | 19 ++++ src/importsMap.jsx | 2 + src/routes.json | 12 +++ src/views/rooms/management/ListRoomLists.jsx | 76 ++++++++++++++++ src/views/rooms/management/ListRooms.jsx | 91 ++++++++++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 src/views/rooms/management/ListRoomLists.jsx create mode 100644 src/views/rooms/management/ListRooms.jsx diff --git a/src/_nav.jsx b/src/_nav.jsx index 01007acb414a..3f44cf5a1bde 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -707,6 +707,25 @@ const _nav = [ }, ], }, + { + component: CNavGroup, + name: ' Room Management', + section: 'Email & Exchange', + to: '/rooms/management', + icon: , + items: [ + { + component: CNavItem, + name: 'Rooms', + to: '/rooms/management/list-rooms', + }, + { + component: CNavItem, + name: 'Room Lists', + to: '/rooms/management/room-lists', + } + ] + }, { component: CNavGroup, name: 'Reports', diff --git a/src/importsMap.jsx b/src/importsMap.jsx index 741d722bc721..36fbf322051d 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -101,6 +101,8 @@ import React from 'react' "/email/spamfilter/list-spamfilter": React.lazy(() => import('./views/email-exchange/spamfilter/Spamfilter')), "/email/spamfilter/deploy": React.lazy(() => import('./views/email-exchange/spamfilter/DeploySpamfilter')), "/email/spamfilter/list-templates": React.lazy(() => import('./views/email-exchange/spamfilter/ListSpamfilterTemplates')), + "/rooms/management/list-rooms": React.lazy(() => import('./views/rooms/management/ListRooms')), + "/rooms/management/room-lists": React.lazy(() => import('./views/rooms/management/ListRoomLists')), "/email/tools/mailbox-restore-wizard": React.lazy(() => import('./views/email-exchange/tools/MailboxRestoreWizard')), "/email/tools/mailbox-restores": React.lazy(() => import('./views/email-exchange/tools/MailboxRestores')), "/email/tools/mail-test": React.lazy(() => import('./views/email-exchange/tools/MailTest')), diff --git a/src/routes.json b/src/routes.json index 4c9a675a515d..0797edb55310 100644 --- a/src/routes.json +++ b/src/routes.json @@ -690,6 +690,18 @@ "component": "views/email-exchange/spamfilter/ListSpamfilterTemplates", "allowedRoles": ["admin", "editor", "readonly"] }, + { + "path": "/rooms/management/list-rooms", + "name": "Rooms", + "component": "views/rooms/management/ListRooms", + "allowedRoles": ["admin", "editor", "readonly"] + }, + { + "path": "/rooms/management/room-lists", + "name": "Room Lists", + "component": "views/rooms/management/ListRoomLists", + "allowedRoles": ["admin", "editor", "readonly"] + }, { "path": "/email/tools/mailbox-restore-wizard", "name": "Mailbox Restore Wizard", diff --git a/src/views/rooms/management/ListRoomLists.jsx b/src/views/rooms/management/ListRoomLists.jsx new file mode 100644 index 000000000000..3da41e5c6fd3 --- /dev/null +++ b/src/views/rooms/management/ListRoomLists.jsx @@ -0,0 +1,76 @@ +import React from 'react' +import { useSelector } from 'react-redux' +import { CButton } from '@coreui/react' +import { faEye, faEdit } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { Link } from 'react-router-dom' +import { CippPageList } from 'src/components/layout' +import { CellTip } from 'src/components/tables' + +const RoomLists = () => { + const tenant = useSelector((state) => state.app.currentTenant) + /* const Actions = (row, rowIndex, formatExtraData) => ( + <> + + + + + + + )*/ + + const columns = [ + { + name: 'Name', + selector: (row) => row['displayName'], + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + maxWidth: '500px', + }, + { + name: 'Coordinates', + selector: (row) => row['geoCoordinates'], + sortable: true, + exportSelector: 'geoCoordinates', + maxWidth: '200px', + }, + { + name: 'PlaceId', + selector: (row) => row['placeId'], + sortable: true, + cell: (row) => CellTip(row['placeId']), + exportSelector: 'placeId', + maxWidth: '300px', + }, + /*{ + name: 'Address', + selector: (row) => row['address'], + sortable: true, + cell: (row) => CellTip(row['address']), + exportSelector: 'address', + maxWidth: '200px', + },*/ + /*{ + name: 'Actions', + cell: Actions, + maxWidth: '80px', + },*/ + ] + + return ( + + ) +} + +export default RoomLists diff --git a/src/views/rooms/management/ListRooms.jsx b/src/views/rooms/management/ListRooms.jsx new file mode 100644 index 000000000000..a94a60fb8b12 --- /dev/null +++ b/src/views/rooms/management/ListRooms.jsx @@ -0,0 +1,91 @@ +import React from 'react' +import { useSelector } from 'react-redux' +import { CButton } from '@coreui/react' +import { faEye, faEdit } from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { Link } from 'react-router-dom' +import { CippPageList } from 'src/components/layout' +import { CellTip } from 'src/components/tables' + +const Rooms = () => { + const tenant = useSelector((state) => state.app.currentTenant) + /* const Actions = (row, rowIndex, formatExtraData) => ( + <> + + + + + + + )*/ + + const columns = [ + { + name: 'Name', + selector: (row) => row['displayName'], + sortable: true, + cell: (row) => CellTip(row['displayName']), + exportSelector: 'displayName', + }, + { + name: 'Building', + selector: (row) => row['building'], + sortable: true, + exportSelector: 'building', + maxWidth: '200px', + }, + { + name: 'Floor', + selector: (row) => row['floorNumber'], + sortable: true, + cell: (row) => CellTip(row['floorNumber']), + exportSelector: 'floorNumber', + maxWidth: '100px', + }, + { + name: 'Capacity', + selector: (row) => row['capacity'], + sortable: true, + cell: (row) => CellTip(row['capacity']), + exportSelector: 'capacity', + maxWidth: '100px', + }, + { + name: 'bookingType', + selector: (row) => row['bookingType'], + sortable: true, + cell: (row) => CellTip(row['bookingType']), + exportSelector: 'bookingType', + maxWidth: '200px', + }, + /*{ + name: 'Address', + selector: (row) => row['address'], + sortable: true, + cell: (row) => CellTip(row['address']), + exportSelector: 'address', + maxWidth: '100px', + },*/ + /*{ + name: 'Actions', + cell: Actions, + maxWidth: '80px', + },*/ + ] + + return ( + + ) +} + +export default Rooms From ec0741e7973a086b1de4ebd4cedbb9c5cef05f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Thu, 2 May 2024 20:53:26 +0200 Subject: [PATCH 02/92] Add new standard for Global Quarantine Notification Interval --- src/data/standards.json | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index 2766676a8ce5..8f13c61f5b1f 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -487,6 +487,36 @@ "impact": "Low Impact", "impactColour": "info" }, + { + "name": "standards.GlobalQuarantineNotifications", + "cat": "Exchange Standards", + "tag": ["lowimpact"], + "helpText": "Sets the Global Quarantine Notification Interval to the selected value. Determines how often the quarantine notification is sent to users.", + "addedComponent": [ + { + "type": "Select", + "label": "Select value", + "name": "standards.GlobalQuarantineNotifications.NotificationInterval", + "values": [ + { + "label": "4 hours", + "value": "04:00:00" + }, + { + "label": "1 day/Daily", + "value": "1.00:00:00" + }, + { + "label": "7 days/Weekly", + "value": "7.00:00:00" + } + ] + } + ], + "label": "Set Global Quarantine Notification Interval", + "impact": "Low Impact", + "impactColour": "info" + }, { "name": "standards.DisableTNEF", "cat": "Exchange Standards", From 3477cb2ccc7a37837de5af3120640e9d7c336b43 Mon Sep 17 00:00:00 2001 From: Esco Date: Thu, 2 May 2024 21:17:05 +0200 Subject: [PATCH 03/92] Added checkbox to QuarantineList --- .../administration/QuarantineList.jsx | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/views/email-exchange/administration/QuarantineList.jsx b/src/views/email-exchange/administration/QuarantineList.jsx index a97211466431..35c66dacc21f 100644 --- a/src/views/email-exchange/administration/QuarantineList.jsx +++ b/src/views/email-exchange/administration/QuarantineList.jsx @@ -98,7 +98,7 @@ const QuarantineList = () => { name: 'Reason', sortable: true, exportSelector: 'Type', - maxWidth: '150px', + maxWidth: '200px', }, { selector: (row) => row['ReceivedTime'], @@ -126,7 +126,7 @@ const QuarantineList = () => { { name: 'Actions', cell: Offcanvas, - maxWidth: '150px', + maxWidth: '100px', }, ] @@ -139,6 +139,32 @@ const QuarantineList = () => { reportName: `${tenant?.defaultDomainName}-Mailbox-Quarantine`, path: '/api/ListMailQuarantine', columns, + tableProps: { + selectableRows: true, + actionsList: [ + { + label: 'Release', + color: 'info', + modal: true, + modalUrl: `/api/ExecQuarantineManagement?TenantFilter=${tenant.defaultDomainName}&ID=!Identity&Type=Release`, + modalMessage: 'Are you sure you want to release these messages?', + }, + { + label: 'Deny', + color: 'info', + modal: true, + modalUrl: `/api/ExecQuarantineManagement?TenantFilter=${tenant.defaultDomainName}&ID=!Identity&Type=Deny`, + modalMessage: 'Are you sure you want to deny these messages?', + }, + { + label: 'Release & Allow Sender', + color: 'info', + modal: true, + modalUrl: `/api/ExecQuarantineManagement?TenantFilter=${tenant.defaultDomainName}&ID=!Identity&Type=Release&AllowSender=true`, + modalMessage: 'Are you sure you want to release these messages, and add the senders to the whitelist?', + }, + ] + }, params: { TenantFilter: tenant?.defaultDomainName }, }} /> From 55aab7427c1efe76ea3ea235ce3acf80c93c4804 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 3 May 2024 11:32:44 +0200 Subject: [PATCH 04/92] comma correction --- src/_nav.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_nav.jsx b/src/_nav.jsx index 3f44cf5a1bde..b0ec445ccd13 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -723,8 +723,8 @@ const _nav = [ component: CNavItem, name: 'Room Lists', to: '/rooms/management/room-lists', - } - ] + }, + ], }, { component: CNavGroup, From 9823b09042b29909c4807e9e18b2d3f6c3e65192 Mon Sep 17 00:00:00 2001 From: peter-fisher <58091301+peter-fisher@users.noreply.github.com> Date: Fri, 3 May 2024 12:54:27 -0400 Subject: [PATCH 05/92] Update GDAPRoles.json Add Viva Goals Administrator and Viva Pulse Administrator roles --- src/data/GDAPRoles.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/data/GDAPRoles.json b/src/data/GDAPRoles.json index adc846cf3028..bf14e31159e5 100644 --- a/src/data/GDAPRoles.json +++ b/src/data/GDAPRoles.json @@ -671,6 +671,22 @@ "Name": "Virtual Visits Administrator", "ObjectId": "e300d9e7-4a2b-4295-9eff-f1c78b36cc98" }, + { + "ExtensionData": {}, + "Description": "Manage and configure all aspects of Microsoft Viva Goals.", + "IsEnabled": true, + "IsSystem": true, + "Name": "Viva Goals Administrator", + "ObjectId": "92b086b3-e367-4ef2-b869-1de128fb986e" + }, + { + "ExtensionData": {}, + "Description": "Can manage all settings for Microsoft Viva Pulse app.", + "IsEnabled": true, + "IsSystem": true, + "Name": "Viva Pulse Administrator", + "ObjectId": "87761b17-1ed2-4af3-9acd-92a150038160" + }, { "ExtensionData": {}, "Description": "Can provision and manage all aspects of Cloud PCs.", From ce8861b120708be066fc61c175801980ab822534 Mon Sep 17 00:00:00 2001 From: peter-fisher <58091301+peter-fisher@users.noreply.github.com> Date: Fri, 3 May 2024 12:55:28 -0400 Subject: [PATCH 06/92] Update GDAPRoles.json Add Viva Goals Administrator and Viva Pulse Administrator roles --- public/GDAPRoles.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/public/GDAPRoles.json b/public/GDAPRoles.json index adc846cf3028..bf14e31159e5 100644 --- a/public/GDAPRoles.json +++ b/public/GDAPRoles.json @@ -671,6 +671,22 @@ "Name": "Virtual Visits Administrator", "ObjectId": "e300d9e7-4a2b-4295-9eff-f1c78b36cc98" }, + { + "ExtensionData": {}, + "Description": "Manage and configure all aspects of Microsoft Viva Goals.", + "IsEnabled": true, + "IsSystem": true, + "Name": "Viva Goals Administrator", + "ObjectId": "92b086b3-e367-4ef2-b869-1de128fb986e" + }, + { + "ExtensionData": {}, + "Description": "Can manage all settings for Microsoft Viva Pulse app.", + "IsEnabled": true, + "IsSystem": true, + "Name": "Viva Pulse Administrator", + "ObjectId": "87761b17-1ed2-4af3-9acd-92a150038160" + }, { "ExtensionData": {}, "Description": "Can provision and manage all aspects of Cloud PCs.", From 8b7a1ab55300da51ae9040b7832cc0a84b79e68a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 4 May 2024 02:14:52 +0200 Subject: [PATCH 07/92] prettified SAM wizard --- src/views/cipp/Setup.jsx | 145 ++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 71 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index c0a728ff8ec7..62f8fced70c8 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -49,11 +49,6 @@ Error.propTypes = { } const Setup = () => { - const [setupDone, setSetupdone] = useState(false) - const valbutton = (value) => - getResults.data?.step < 5 - ? undefined - : `You do not have to click next. Finish the wizard via the setup button below. After it says "Setup Completed" you may browse away from this page.` const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery() const onSubmit = (values) => { @@ -72,7 +67,6 @@ const Setup = () => { path: 'api/ExecSAMSetup', params: { CreateSAM: true, partnersetup: true }, }) - setSetupdone(false) } useInterval( @@ -82,19 +76,35 @@ const Setup = () => { path: 'api/ExecSAMSetup', params: { CheckSetupProcess: true, step: getResults.data?.step }, }) - } else { - setSetupdone(true) } }, 10000, getResults.data, ) const formValues = {} + + const stepsDetails = [ + { id: 1, text: 'Step 1 - First Login' }, + { id: 2, text: 'Step 2 - Creating Application' }, + { id: 3, text: 'Step 3 - Application Approval' }, + { id: 4, text: 'Step 4 - Receiving Token' }, + { id: 5, text: 'Step 5 - Finishing Setup' }, + ] + const RenderSteps = ({ currentStep = 0 }) => ( + <> + {stepsDetails.slice(0, currentStep - 1).map((step) => ( +
+ {step.text} - Completed +
+ ))} + + ) return (
@@ -112,7 +122,7 @@ const Setup = () => { rel="noreferrer" target="_blank" > - here. + here @@ -134,7 +144,11 @@ const Setup = () => {
- +

Step 2

Enter the secure application model credentials.
@@ -147,29 +161,30 @@ const Setup = () => {
Remember to login under a account that has been added to the correct GDAP groups and the group 'AdminAgents'.
- {getResults.isUninitialized && genericGetRequest({ path: 'api/ExecListAppId' })} - {getResults.isSuccess && ( - <> - - - - Refresh Graph Token - - - - - - )} + {getResults.isUninitialized && genericGetRequest({ path: 'api/ExecListAppId' })} + {getResults.isSuccess && ( + <> + + + + + Refresh Graph Token + + + + + + + )}

- When clicking the button below, the setup wizard starts. This is a 5 step process. - Please use a Global Administrator to perform these tasks. You can restart the process - at any time, by clicking on the start button once more. + Click the button below to start the setup wizard, remember to check the SAM Wizard + documentation before starting the wizard.

{ className="btn btn-primary" type="button" onClick={() => startCIPPSetup(true)} - validate={() => valbutton()} > Start Setup Wizard - -
- {getResults.isFetching && Loading} {getResults.isSuccess && ( <> - {getResults.data?.step < 5 ? ( + + {getResults.data?.step < 5 && getResults.data?.step > 0 && ( - ) : ( - )} - Step {getResults.data?.step} - {getResults.data.message}{' '} - {getResults.data.url && ( - - HERE - + {getResults.data?.step > 0 && ( + <> + Step {getResults.data?.step} - {getResults.data.message}{' '} + {getResults.data.url && ( + + HERE + + )} + )} )} @@ -251,40 +265,29 @@ const Setup = () => { /> + + +
+ Submit info +
+
+
+ {postResults.isFetching && ( + + Loading + + )} + {postResults.isSuccess && {postResults.data.Results}}
-
- - -
-

Step 3

-
Confirm and apply
-
-
- {!postResults.isSuccess && ( - - {(props) => { - return ( - <> - - - - {usedWizard && - 'You have used the setup wizard. You can close this screen. Setup has been completed.'} - {!usedWizard && - 'You are sending your own Secure Application Model setup to the Keyvault. For security reasons we do not show the keys. Please make sure you have entered the keys correctly.'} - - - - ) - }} - - )} - {postResults.isFetching && ( - - Loading - - )} - {postResults.isSuccess && {postResults.data.Results}} + + {(props) => { + if (props.values.SetupType === 'ExistingSAM') { + setNoSubmit(false) + } else { + setNoSubmit(true) + } + }} +
From 3109e1fe6d503132a43597b40041c1dcf6599a7f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 4 May 2024 02:24:00 +0200 Subject: [PATCH 08/92] added clear callout --- src/views/cipp/Setup.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 62f8fced70c8..76092da5b2d3 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -7,6 +7,7 @@ import { CippWizard } from 'src/components/layout' import PropTypes from 'prop-types' import { Condition, RFFCFormInput, RFFCFormRadio } from 'src/components/forms' import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { Link } from 'react-router-dom' function useInterval(callback, delay, state) { const savedCallback = useRef() @@ -220,6 +221,13 @@ const Setup = () => { )} + {getResults.data?.step === 5 && ( + + + Setup complete. We suggest running a Permissions Check in our{' '} + Application Settings page. + + )} From c7b5064c404094ca68c93b3d4c74a4804c826452 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 4 May 2024 02:29:15 +0200 Subject: [PATCH 09/92] updating wizard --- src/views/cipp/Setup.jsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 76092da5b2d3..79f31552d768 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -86,10 +86,9 @@ const Setup = () => { const stepsDetails = [ { id: 1, text: 'Step 1 - First Login' }, - { id: 2, text: 'Step 2 - Creating Application' }, - { id: 3, text: 'Step 3 - Application Approval' }, - { id: 4, text: 'Step 4 - Receiving Token' }, - { id: 5, text: 'Step 5 - Finishing Setup' }, + { id: 2, text: 'Step 2 - Creating Application & Approving Application' }, + { id: 3, text: 'Step 3 - Receiving Token' }, + { id: 4, text: 'Step 4 - Finishing Setup' }, ] const RenderSteps = ({ currentStep = 0 }) => ( <> @@ -221,7 +220,7 @@ const Setup = () => { )} - {getResults.data?.step === 5 && ( + {getResults.data?.step === 4 && ( Setup complete. We suggest running a Permissions Check in our{' '} From 507951bd740e8ab666082459f4c5768339b7e935 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 4 May 2024 02:36:21 +0200 Subject: [PATCH 10/92] fixes incorrect showing of completed steps --- src/views/cipp/Setup.jsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 79f31552d768..9f8822c1eae0 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -92,11 +92,12 @@ const Setup = () => { ] const RenderSteps = ({ currentStep = 0 }) => ( <> - {stepsDetails.slice(0, currentStep - 1).map((step) => ( -
- {step.text} - Completed -
- ))} + {currentStep > 0 && + stepsDetails.slice(0, currentStep - 1).map((step) => ( +
+ {step.text} - Completed +
+ ))} ) return ( From c9ab7cb9e29f8e4660e47f03619fb116a3d0224d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 4 May 2024 02:42:53 +0200 Subject: [PATCH 11/92] prettification --- src/views/cipp/Setup.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 9f8822c1eae0..080c14f2ffc4 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -208,7 +208,7 @@ const Setup = () => { {getResults.data?.step < 5 && getResults.data?.step > 0 && ( )} - {getResults.data?.step > 0 && ( + {getResults.data?.step > 0 && getResults.data?.step < 5 && ( <> Step {getResults.data?.step} - {getResults.data.message}{' '} {getResults.data.url && ( @@ -221,7 +221,7 @@ const Setup = () => { )} - {getResults.data?.step === 4 && ( + {getResults.data?.step === 5 && ( Setup complete. We suggest running a Permissions Check in our{' '} From b62c98e96b0b4d3dcdd413d22fa0eab2c4af977d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 12:25:19 +0200 Subject: [PATCH 12/92] improvements to experience. --- src/views/cipp/Setup.jsx | 43 +- .../cipp/app-settings/SettingsGeneral.jsx | 73 +-- .../tenant/administration/AlertWizard.jsx | 450 +++++------------- 3 files changed, 194 insertions(+), 372 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 080c14f2ffc4..82b9eed1e412 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -6,7 +6,11 @@ import { faCheck, faExclamationTriangle } from '@fortawesome/free-solid-svg-icon import { CippWizard } from 'src/components/layout' import PropTypes from 'prop-types' import { Condition, RFFCFormInput, RFFCFormRadio } from 'src/components/forms' -import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { + useLazyExecPermissionsAccessCheckQuery, + useLazyGenericGetRequestQuery, + useLazyGenericPostRequestQuery, +} from 'src/store/api/app' import { Link } from 'react-router-dom' function useInterval(callback, delay, state) { @@ -50,6 +54,7 @@ Error.propTypes = { } const Setup = () => { + const [checkPermissions, permissionsResult] = useLazyExecPermissionsAccessCheckQuery() const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery() const onSubmit = (values) => { @@ -88,7 +93,7 @@ const Setup = () => { { id: 1, text: 'Step 1 - First Login' }, { id: 2, text: 'Step 2 - Creating Application & Approving Application' }, { id: 3, text: 'Step 3 - Receiving Token' }, - { id: 4, text: 'Step 4 - Finishing Setup' }, + { id: 4, text: 'Step 4 - Finishing Authentication Setup' }, ] const RenderSteps = ({ currentStep = 0 }) => ( <> @@ -159,8 +164,8 @@ const Setup = () => { Click the buttons below to refresh your token. -
Remember to login under a account that has been added to the correct GDAP - groups and the group 'AdminAgents'. +
Remember to login under a service account that has been added to the correct + GDAP groups and the group 'AdminAgents'.
{getResults.isUninitialized && genericGetRequest({ path: 'api/ExecListAppId' })} @@ -184,8 +189,24 @@ const Setup = () => {

- Click the button below to start the setup wizard, remember to check the SAM Wizard - documentation before starting the wizard. + Click the button below to start the setup wizard. You will need the following + prerequisites: +

  • + A CIPP Service Account. For more information on how to create a service account + click{' '} + + here + +
  • +
  • (Temporary) Global Administrator permissions for the CIPP Service Account
  • +
  • + Multi-factor authentication enabled for the CIPP Service Account, with no trusted + locations or other exclusions. +
  • { )} {getResults.data?.step === 5 && ( - - - Setup complete. We suggest running a Permissions Check in our{' '} - Application Settings page. - +

    + {permissionsResult.isFetching && } Authentication setup has been + finished. We are now checking your access to your tenants. + {checkPermissions()} +

    )}
    diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx index 98a34210c72b..4ad0ba4cadc2 100644 --- a/src/views/cipp/app-settings/SettingsGeneral.jsx +++ b/src/views/cipp/app-settings/SettingsGeneral.jsx @@ -290,36 +290,49 @@ export function SettingsGeneral() { /> )} - - {permissionsResult.data.Results?.Messages && ( - <> - {permissionsResult.data.Results?.Messages?.map((m, idx) => ( -
    {m}
    - ))} - - )} - {permissionsResult.data.Results?.MissingPermissions.length > 0 && ( - <> - Your Secure Application Model is missing the following permissions. See the - documentation on how to add permissions{' '} - - here - - . - - {permissionsResult.data.Results?.MissingPermissions?.map((r, index) => ( - {r} - ))} - - - )} -
    + + + + {permissionsResult.data.Results?.Messages && ( + <> + {permissionsResult.data.Results?.Messages?.map((m, idx) => ( +
    {m}
    + ))} + + )} +
    +
    + + + {permissionsResult.data.Results?.ErrorMessages && ( + <> + {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( +
    {m}
    + ))} + + )} + {permissionsResult.data.Results?.MissingPermissions.length > 0 && ( + <> + Your Secure Application Model is missing the following permissions. See + the documentation on how to add permissions{' '} + + here + + . + + {permissionsResult.data.Results?.MissingPermissions?.map((r, index) => ( + {r} + ))} + + + )} +
    +
    +
    )} diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index c2e920354e15..2d8eb08c46d2 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -1,346 +1,134 @@ -import React from 'react' -import { CCol, CRow, CForm, CListGroup, CListGroupItem, CCallout, CSpinner } from '@coreui/react' -import { Field, FormSpy } from 'react-final-form' +import React, { useEffect, useState } from 'react' +import { + CButton, + CCallout, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CForm, + CRow, + CSpinner, + CWidgetStatsA, +} from '@coreui/react' +import useQuery from 'src/hooks/useQuery' +import { useDispatch } from 'react-redux' +import { Form } from 'react-final-form' +import { CippPage } from 'src/components/layout' +import { ModalService, TenantSelectorMultiple } from 'src/components/utilities' +import { RFFCFormInput } from 'src/components/forms/RFFComponents' +import { useListTenantQuery } from 'src/store/api/tenants' +import { + useLazyExecPermissionsAccessCheckQuery, + useLazyGenericPostRequestQuery, +} from 'src/store/api/app' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCheck, faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons' -import { CippWizard } from 'src/components/layout' -import { WizardTableField } from 'src/components/tables' -import PropTypes from 'prop-types' -import { Condition, RFFCFormSelect, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms' -import { useLazyGenericPostRequestQuery } from 'src/store/api/app' -import countryList from 'src/data/countryList.json' - -const Error = ({ name }) => ( - - touched && error ? ( - - - {error} - - ) : null - } - /> -) - -Error.propTypes = { - name: PropTypes.string.isRequired, -} - -const requiredArray = (value) => (value && value.length !== 0 ? undefined : 'Required') +import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' +import CippPrettyCard from 'src/components/contentcards/CippPrettyCard' +import CippButtonCard from 'src/components/contentcards/CippButtonCard' const AlertWizard = () => { + const dispatch = useDispatch() + let query = useQuery() + const tenantDomain = query.get('tenantFilter') + const customerId = query.get('customerId') + const [queryError, setQueryError] = useState(false) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() - const handleSubmit = async (values) => { - Object.keys(values).filter(function (x) { - if (values[x] === null) { - delete values[x] - } - return null - }) - values.selectedTenants.map( - (tenant) => (values[`Select_${tenant.defaultDomainName}`] = tenant.defaultDomainName), - ) - genericPostRequest({ path: '/api/AddAlert', values: values }) - } - - const formValues = {} + const { + data: tenant = {}, + isFetching, + error, + isSuccess, + } = useListTenantQuery(tenantDomain, customerId) + const onSubmit = (values) => { + const shippedValues = { + tenantid: tenantDomain, + displayName: values.displayName, + defaultDomainName: values.defaultDomainName, + customerId: customerId, + } + genericPostRequest({ path: '/api/AlertWizard', values: shippedValues }) + } + const initialValues = { + ...tenant[0], + } return ( - - -
    -

    Step 1

    -
    Choose a tenant
    -
    -
    - - {(props) => ( - row['displayName'], - sortable: true, - exportselector: 'displayName', - }, - { - name: 'Default Domain Name', - selector: (row) => row['defaultDomainName'], - sortable: true, - exportselector: 'mail', - }, - ]} - fieldProps={props} - /> - )} - - -
    -
    - -
    -

    Step 2

    -
    Select Legacy Alerts to receive
    -
    -
    - -

    - Alerts setup on this page are considered legacy. These alerts run every 15 minutes and - do not use our advanced alerting engine. -

    - - - -
    - - - - - - - - - - - - - - - - - - - - - -
    + + {!queryError && ( + <> + + + + + + + + + + + + + + -
    - -
    -
    - -
    -

    Step 3

    -
    Select webhook alerts
    -
    -
    - -

    - This setting will subscribe CIPP to receive the audit logs from this tenant directly. - You can then use the Alert Rules page to create alerts or take actions based on these - logs. -

    - + + + Current Settings + + + {isFetching && } + {error && Error loading Tenant} + {isSuccess && ( +
    { + return ( + + + + + + + + + + Edit Tenant + {postResults.isFetching && ( + + )} + + + + {postResults.isSuccess && ( + {postResults.data.Results} + )} + + ) + }} + /> + )} + + - -
    - - -
    -

    Step 3

    -
    Confirm and apply
    -
    -
    - {!postResults.isSuccess && ( - - {/* eslint-disable react/prop-types */} - {(props) => { - return ( - <> - - - - - - Alert on users without any form of MFA - - - - Alert on admins without any form of MFA - - - - Alert on new users added to any admin role - - - - Alert on changed admin Passwords - - - - Alert if Defender is not running - - - - Alert on Defender Malware - - - - Alert on 90% mailbox quota used - - - - Alert on unused licenses - - - - Alert on overused licenses - - - - Alert on expiring application secrets - - - - Alert on expiring APN certificates - - - - Alert on expiring VPP tokens - - - - Alert on expiring DEP tokens - - - - Alert on no CA policies - - - - Alert on Security Defaults automatic enablement - - - - - - - ) - }} - - )} - {postResults.isFetching && ( - - Loading - - )} - {postResults.isSuccess && ( - - {postResults.data.Results.map((message, idx) => { - return
  • {message}
  • - })} -
    - )} -
    -
    - + + )} + ) } From 94313cbfcf487ebb573c3668c4111d1c3702b490 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 12:30:03 +0200 Subject: [PATCH 13/92] improvements to setup experience. --- src/views/cipp/Setup.jsx | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 82b9eed1e412..41bd3eb3f8e9 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -244,11 +244,35 @@ const Setup = () => { {getResults.data?.step === 5 && (

    - {permissionsResult.isFetching && } Authentication setup has been - finished. We are now checking your access to your tenants. + {permissionsResult.isFetching && } Authentication has been received. + Checking if all prerequisites are met to connect to your tenants. {checkPermissions()}

    )} + + + + {permissionsResult.data.Results?.Messages && ( + <> + {permissionsResult.data.Results?.Messages?.map((m, idx) => ( +
    {m}
    + ))} + + )} +
    +
    + + + {permissionsResult.data.Results?.ErrorMessages && ( + <> + {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( +
    {m}
    + ))} + + )} +
    +
    +
    From f940bfd818c7fe27bd6c75fe8c92a4858c855724 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 12:42:15 +0200 Subject: [PATCH 14/92] conditional loading --- src/views/cipp/Setup.jsx | 48 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 41bd3eb3f8e9..50c5476617fc 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -250,28 +250,32 @@ const Setup = () => {

    )} - - - {permissionsResult.data.Results?.Messages && ( - <> - {permissionsResult.data.Results?.Messages?.map((m, idx) => ( -
    {m}
    - ))} - - )} -
    -
    - - - {permissionsResult.data.Results?.ErrorMessages && ( - <> - {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( -
    {m}
    - ))} - - )} -
    -
    + {permissionsResult.data?.Results && ( + <> + + + {permissionsResult.data.Results?.Messages && ( + <> + {permissionsResult.data.Results?.Messages?.map((m, idx) => ( +
    {m}
    + ))} + + )} +
    +
    + + + {permissionsResult.data.Results?.ErrorMessages && ( + <> + {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( +
    {m}
    + ))} + + )} +
    +
    + + )}
    From 833febde272f4fab930cec207b72bf5fc164e848 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 12:48:51 +0200 Subject: [PATCH 15/92] prevent rerenders --- src/views/cipp/Setup.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 50c5476617fc..c0d0da535f97 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -246,7 +246,7 @@ const Setup = () => {

    {permissionsResult.isFetching && } Authentication has been received. Checking if all prerequisites are met to connect to your tenants. - {checkPermissions()} + {permissionsResult.isUninitialized && checkPermissions()}

    )} From 82298e4a0e74245ee13a283ecb3bd25985536331 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 13:16:01 +0200 Subject: [PATCH 16/92] redo check if step is 5 again --- src/views/cipp/Setup.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index c0d0da535f97..d533af7c4ffe 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -216,7 +216,7 @@ const Setup = () => { type="button" onClick={() => startCIPPSetup(true)} > - Start Setup Wizard + {getResults.isFetching && } Start Setup Wizard
    @@ -246,7 +246,7 @@ const Setup = () => {

    {permissionsResult.isFetching && } Authentication has been received. Checking if all prerequisites are met to connect to your tenants. - {permissionsResult.isUninitialized && checkPermissions()} + {getResults.data?.step === 5 && checkPermissions()}

    )} From 1f684c9813e1b614e2b512bcf47e675e39ffe81a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 13:51:00 +0200 Subject: [PATCH 17/92] prettification --- .../cipp/app-settings/SettingsGeneral.jsx | 110 +++++------------- 1 file changed, 32 insertions(+), 78 deletions(-) diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx index 4ad0ba4cadc2..32a156c5a2e1 100644 --- a/src/views/cipp/app-settings/SettingsGeneral.jsx +++ b/src/views/cipp/app-settings/SettingsGeneral.jsx @@ -20,6 +20,7 @@ import { CListGroup, CListGroupItem, CRow, + CTable, } from '@coreui/react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' @@ -29,6 +30,7 @@ import { CippTable } from 'src/components/tables/index.js' import { TenantSelectorMultiple } from 'src/components/utilities/index.js' import { SettingsGeneralRow } from 'src/views/cipp/app-settings/components/SettingsGeneralRow.jsx' import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import { ListGroupContentCard } from 'src/components/contentcards' /** * SettingsGeneral component. @@ -139,72 +141,6 @@ export function SettingsGeneral() { checkAccess({ tenantDomains: AllTenantSelector }) } - function getTokenOffcanvasProps({ tokenResults }) { - let tokenDetails = tokenResults.AccessTokenDetails - let helpLinks = tokenResults.Links - let tokenOffcanvasGroups = [] - if (tokenDetails?.Name !== '') { - let tokenItems = [] - let tokenOffcanvasGroup = {} - tokenItems.push({ - heading: 'User', - content: tokenDetails?.Name, - }) - tokenItems.push({ - heading: 'UPN', - content: tokenDetails?.UserPrincipalName, - }) - tokenItems.push({ - heading: 'App Registration', - content: ( - - {tokenDetails?.AppName} - - ), - }) - tokenItems.push({ - heading: 'IP Address', - content: tokenDetails?.IPAddress, - }) - tokenItems.push({ - heading: 'Auth Methods', - content: tokenDetails?.AuthMethods.join(', '), - }) - tokenItems.push({ - heading: 'Tenant ID', - content: tokenDetails?.TenantId, - }) - tokenOffcanvasGroup.items = tokenItems - tokenOffcanvasGroup.title = 'Claims' - tokenOffcanvasGroups.push(tokenOffcanvasGroup) - } - - if (helpLinks.length > 0) { - let linkItems = [] - let linkItemGroup = {} - helpLinks.map((link, idx) => - linkItems.push({ - heading: '', - content: ( - - {link.Text} - - ), - }), - ) - linkItemGroup.title = 'Help Links' - linkItemGroup.items = linkItems - if (linkItemGroup.items.length > 0) { - tokenOffcanvasGroups.push(linkItemGroup) - } - } - - return tokenOffcanvasGroups - } - const tableProps = { pagination: false, actions: [ @@ -276,18 +212,36 @@ export function SettingsGeneral() { <> {permissionsResult.data.Results?.AccessTokenDetails?.Name !== '' && ( <> - setTokenOffcanvasVisible(true)}> - Details - - setTokenOffcanvasVisible(false)} - /> + {console.log(permissionsResult.data.Results)} + { + //create a small table, headers: Name,UserPrinicipalName, AuthMethods + } + + + + Authentication User + Authentication IP + Application + + + + + + {permissionsResult.data.Results?.AccessTokenDetails?.UserPrincipalName} + + {permissionsResult.data.Results?.AccessTokenDetails?.IPAddress} + + + Link + + + + + )} From 591bb9bc1b96f9a421811ce000aeb214c86d6736 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 14:07:29 +0200 Subject: [PATCH 18/92] prevent reload --- src/views/cipp/Setup.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index d533af7c4ffe..ea00f89b3cfd 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -246,7 +246,7 @@ const Setup = () => {

    {permissionsResult.isFetching && } Authentication has been received. Checking if all prerequisites are met to connect to your tenants. - {getResults.data?.step === 5 && checkPermissions()} + {permissionsResult.isUninitialized && checkPermissions()}

    )} From c72a112670f589deb3652bdd0cdd1f273907dd15 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 14:14:11 +0200 Subject: [PATCH 19/92] length for errors --- src/views/cipp/Setup.jsx | 2 +- src/views/cipp/app-settings/SettingsGeneral.jsx | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index ea00f89b3cfd..ed9a2f5222ef 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -265,7 +265,7 @@ const Setup = () => { - {permissionsResult.data.Results?.ErrorMessages && ( + {permissionsResult.data.Results?.ErrorMessages.length >= 1 && ( <> {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => (
    {m}
    diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx index 32a156c5a2e1..0f4c54f50160 100644 --- a/src/views/cipp/app-settings/SettingsGeneral.jsx +++ b/src/views/cipp/app-settings/SettingsGeneral.jsx @@ -212,10 +212,6 @@ export function SettingsGeneral() { <> {permissionsResult.data.Results?.AccessTokenDetails?.Name !== '' && ( <> - {console.log(permissionsResult.data.Results)} - { - //create a small table, headers: Name,UserPrinicipalName, AuthMethods - } @@ -258,7 +254,7 @@ export function SettingsGeneral() {
    - {permissionsResult.data.Results?.ErrorMessages && ( + {permissionsResult.data.Results?.ErrorMessages.length >= 1 && ( <> {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => (
    {m}
    From a387743927828318baa717ee4b72dfc40694feaa Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 14:14:39 +0200 Subject: [PATCH 20/92] nullsafe --- src/views/cipp/Setup.jsx | 2 +- src/views/cipp/app-settings/SettingsGeneral.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index ed9a2f5222ef..4079e8ae8a61 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -265,7 +265,7 @@ const Setup = () => {
    - {permissionsResult.data.Results?.ErrorMessages.length >= 1 && ( + {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( <> {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => (
    {m}
    diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx index 0f4c54f50160..623a4258dc6b 100644 --- a/src/views/cipp/app-settings/SettingsGeneral.jsx +++ b/src/views/cipp/app-settings/SettingsGeneral.jsx @@ -254,7 +254,7 @@ export function SettingsGeneral() {
    - {permissionsResult.data.Results?.ErrorMessages.length >= 1 && ( + {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( <> {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => (
    {m}
    From 7a5d157d6b67b68ee3c96547ad1464e7fcc63782 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 14:26:19 +0200 Subject: [PATCH 21/92] fixes empty callout --- src/views/cipp/Setup.jsx | 16 +++++++--------- src/views/tenant/administration/AlertWizard.jsx | 5 ++++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/views/cipp/Setup.jsx b/src/views/cipp/Setup.jsx index 4079e8ae8a61..bf09e8b04baf 100644 --- a/src/views/cipp/Setup.jsx +++ b/src/views/cipp/Setup.jsx @@ -264,15 +264,13 @@ const Setup = () => {
    - - {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( - <> - {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( -
    {m}
    - ))} - - )} -
    + {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( + + {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( +
    {m}
    + ))} +
    + )}
    )} diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 2d8eb08c46d2..fd9d82537f4e 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -61,7 +61,10 @@ const AlertWizard = () => { <> - + + Select this option if you'd like to create an alert based on a received Microsoft + Audit log. + From 09c1e749b233a51ea98fdf6cd08cb46c60fd1cfa Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 14:28:26 +0200 Subject: [PATCH 22/92] fixes --- .../cipp/app-settings/SettingsGeneral.jsx | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx index 623a4258dc6b..af9041cd3b2a 100644 --- a/src/views/cipp/app-settings/SettingsGeneral.jsx +++ b/src/views/cipp/app-settings/SettingsGeneral.jsx @@ -253,34 +253,36 @@ export function SettingsGeneral() { - - {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( + {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( + <> {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => (
    {m}
    ))} - )} - {permissionsResult.data.Results?.MissingPermissions.length > 0 && ( - <> - Your Secure Application Model is missing the following permissions. See - the documentation on how to add permissions{' '} - - here - - . - - {permissionsResult.data.Results?.MissingPermissions?.map((r, index) => ( - {r} - ))} - - - )} -
    + {permissionsResult.data.Results?.MissingPermissions.length > 0 && ( + <> + Your Secure Application Model is missing the following permissions. See + the documentation on how to add permissions{' '} + + here + + . + + {permissionsResult.data.Results?.MissingPermissions?.map( + (r, index) => ( + {r} + ), + )} + + + )} +
    + )}
    From 1ae82691b1577affaeb8890f87411b9f197c312c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 6 May 2024 14:32:43 +0200 Subject: [PATCH 23/92] interface changes --- .../cipp/app-settings/SettingsGeneral.jsx | 57 ++++++++++--------- .../tenant/administration/AlertWizard.jsx | 4 +- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx index af9041cd3b2a..04446add8ceb 100644 --- a/src/views/cipp/app-settings/SettingsGeneral.jsx +++ b/src/views/cipp/app-settings/SettingsGeneral.jsx @@ -253,36 +253,37 @@ export function SettingsGeneral() { - {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && ( - - <> - {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( -
    {m}
    - ))} - - {permissionsResult.data.Results?.MissingPermissions.length > 0 && ( + {permissionsResult.data.Results?.ErrorMessages?.length > 0 || + (permissionsResult.data.Results?.MissingPermissions.length > 0 && ( + <> - Your Secure Application Model is missing the following permissions. See - the documentation on how to add permissions{' '} - - here - - . - - {permissionsResult.data.Results?.MissingPermissions?.map( - (r, index) => ( - {r} - ), - )} - + {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => ( +
    {m}
    + ))} - )} -
    - )} + {permissionsResult.data.Results?.MissingPermissions.length > 0 && ( + <> + Your Secure Application Model is missing the following permissions. + See the documentation on how to add permissions{' '} + + here + + . + + {permissionsResult.data.Results?.MissingPermissions?.map( + (r, index) => ( + {r} + ), + )} + + + )} +
    + ))}
    diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index fd9d82537f4e..f2974b2e139c 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -67,7 +67,9 @@ const AlertWizard = () => { - + + Select this option if you'd like to setup an alert based on data processed by CIPP +
    From 5dbd155d5e60ed31bd4106cb3eca59eba698126d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 7 May 2024 11:22:15 +0200 Subject: [PATCH 24/92] new alert wizard prep --- src/data/alerts.json | 93 +++++ .../tenant/administration/AlertWizard.jsx | 341 +++++++++++++++--- 2 files changed, 378 insertions(+), 56 deletions(-) create mode 100644 src/data/alerts.json diff --git a/src/data/alerts.json b/src/data/alerts.json new file mode 100644 index 000000000000..d6c7215f2d04 --- /dev/null +++ b/src/data/alerts.json @@ -0,0 +1,93 @@ +[ + { + "name": "MFAAlertUsers", + "label": "Alert on users without any form of MFA", + "recommendedRunInterval": "1d" + }, + { + "name": "MFAAdmins", + "label": "Alert on admins without any form of MFA", + "recommendedRunInterval": "1d" + }, + { + "name": "NoCAConfig", + "label": "Alert on tenants without a Conditional Access policy, while having Conditional Access licensing available.", + "recommendedRunInterval": "1d" + }, + { + "name": "AdminPassword", + "label": "Alert on changed admin Passwords", + "recommendedRunInterval": "30m" + }, + { + "name": "QuotaUsed", + "label": "Alert on % mailbox quota used", + "requiresInput": true, + "inputLabel": "Enter quota percentage", + "inputName": "QuotaUsedQuota", + "recommendedRunInterval": "4h" + }, + { + "name": "SharePointQuota", + "label": "Alert on % SharePoint quota used", + "requiresInput": true, + "inputLabel": "Enter quota percentage", + "inputName": "SharePointQuotaQuota", + "recommendedRunInterval": "4h" + }, + { + "name": "ExpiringLicenses", + "label": "Alert on licenses expiring in 30 days", + "recommendedRunInterval": "7d" + }, + { + "name": "NewAppApproval", + "label": "Alert on new apps in the application approval list", + "recommendedRunInterval": "30m" + }, + { + "name": "SecDefaultsUpsell", + "label": "Alert on Security Defaults automatic enablement", + "recommendedRunInterval": "1d" + }, + { + "name": "DefenderStatus", + "label": "Alert if Defender is not running (Tenant must be on-boarded in Lighthouse)", + "recommendedRunInterval": "4h" + }, + { + "name": "DefenderMalware", + "label": "Alert on Defender Malware found (Tenant must be on-boarded in Lighthouse)", + "recommendedRunInterval": "4h" + }, + { + "name": "UnusedLicenses", + "label": "Alert on unused licenses", + "recommendedRunInterval": "1d" + }, + { + "name": "OverusedLicenses", + "label": "Alert on overused licenses", + "recommendedRunInterval": "7d" + }, + { + "name": "AppSecretExpiry", + "label": "Alert on expiring application secrets", + "recommendedRunInterval": "1d" + }, + { + "name": "ApnCertExpiry", + "label": "Alert on expiring APN certificates", + "recommendedRunInterval": "1d" + }, + { + "name": "VppTokenExpiry", + "label": "Alert on expiring VPP tokens", + "recommendedRunInterval": "1d" + }, + { + "name": "DepTokenExpiry", + "label": "Alert on expiring DEP tokens", + "recommendedRunInterval": "1d" + } +] diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index f2974b2e139c..479bbf018ae1 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -14,19 +14,21 @@ import { } from '@coreui/react' import useQuery from 'src/hooks/useQuery' import { useDispatch } from 'react-redux' -import { Form } from 'react-final-form' +import { Field, Form, FormSpy } from 'react-final-form' import { CippPage } from 'src/components/layout' -import { ModalService, TenantSelectorMultiple } from 'src/components/utilities' -import { RFFCFormInput } from 'src/components/forms/RFFComponents' -import { useListTenantQuery } from 'src/store/api/tenants' +import { TenantSelector, TenantSelectorMultiple } from 'src/components/utilities' import { - useLazyExecPermissionsAccessCheckQuery, - useLazyGenericPostRequestQuery, -} from 'src/store/api/app' + Condition, + RFFCFormInput, + RFFCFormSwitch, + RFFSelectSearch, +} from 'src/components/forms/RFFComponents' +import { useListTenantQuery } from 'src/store/api/tenants' +import { useLazyGenericPostRequestQuery } from 'src/store/api/app' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' -import CippPrettyCard from 'src/components/contentcards/CippPrettyCard' import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import alertList from 'src/data/alerts.json' const AlertWizard = () => { const dispatch = useDispatch() @@ -35,7 +37,7 @@ const AlertWizard = () => { const customerId = query.get('customerId') const [queryError, setQueryError] = useState(false) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() - + const [alertType, setAlertType] = useState(false) const { data: tenant = {}, isFetching, @@ -55,82 +57,309 @@ const AlertWizard = () => { const initialValues = { ...tenant[0], } + + const recurrenceOptions = [ + { value: '30m', name: 'Every 30 minutes' }, + { value: '1h', name: 'Every hour' }, + { value: '4h', name: 'Every 4 hours' }, + { value: '1d', name: 'Every 1 day' }, + { value: '7d', name: 'Every 7 days' }, + { value: '30d', name: 'Every 30 days' }, + { value: '365d', name: 'Every 365 days' }, + ] + + const presetValues = [ + { value: 'New-InboxRule', name: 'A new Inbox rule is created' }, + { + value: 'New-InboxRule', + name: 'A new Inbox rule is created that forwards e-mails to the RSS feeds folder', + }, + + { value: 'Set-InboxRule', name: 'A existing Inbox rule is edited' }, + { + value: 'Set-InboxRule', + name: 'A existing Inbox rule is edited that forwards e-mails to the RSS feeds folder', + }, + + { + value: 'Add member to role.', + name: 'A user has been added to an admin role', + }, + { + value: 'Add User.', + name: 'A user account was created', + }, + { + value: 'Disable account.', + name: 'A user account has been disabled', + }, + { + value: 'Enable account.', + name: 'A user account has been enabled', + }, + { + value: 'Update StsRefreshTokenValidFrom Timestamp.', + name: 'A user sessions have been revoked', + }, + { + value: 'Disable Strong Authentication.', + name: 'A users MFA has been disabled', + }, + { + value: 'Remove Member from a role.', + name: 'A user has been removed from a role', + }, + { + value: 'Reset user password.', + name: 'A user password has been reset', + }, + { + value: 'UserLoggedInFromUnknownLocation', + name: 'A user has logged in from a location not in the allowed locations list', + }, + { + value: 'Add service principal.', + name: 'A service principal has been created', + }, + { + value: 'Remove service principal.', + name: 'A service principal has been removed', + }, + { + value: 'badRepIP', + name: 'A user has logged in a using a known VPN, Proxy, Or anonymizer', + }, + { + value: 'HostedIP', + name: 'A user has logged in a using a known hosting provider IP', + }, + ] + return ( {!queryError && ( <> - - + + setAlertType('audit')}>Select} + > Select this option if you'd like to create an alert based on a received Microsoft Audit log. - - + + setAlertType('script')}>Select} + > Select this option if you'd like to setup an alert based on data processed by CIPP - - - - - - - - - - - - Current Settings - - - {isFetching && } - {error && Error loading Tenant} - {isSuccess && ( + {alertType === 'audit' && ( + <> + + + + Select the tenants you want to include in this Alert. + + + + + { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) + }} + /> + + )} + {alertType === 'script' && ( + <> + + + +

    Select the tenants you want to include in this Alert.

    + +
    +
    +
    + + + + Add Schedule + {postResults.isFetching && ( + + )} + + } + > { return ( - - - - + + + ({ + value: cmd, + name: cmd.label, + }))} + name="command" + placeholder={'Select a command'} + label="What alerting script should run" /> + + + + + {(props) => { + return ( + + ) + }} + + + + - - - Edit Tenant - {postResults.isFetching && ( - - )} - + + + {(props) => { + const updatedRecurrenceOptions = recurrenceOptions.map( + (opt) => ({ + ...opt, + name: opt.name.replace(' (Recommended)', ''), + }), + ) + const recommendedValue = + props.values.command?.value?.recommendedRunInterval + const option = updatedRecurrenceOptions.find( + (opt) => opt.value === recommendedValue, + ) + if (option) { + option.name += ' (Recommended)' + } + return ( + + ) + }} + + + + + + + + + {postResults.isSuccess && ( - {postResults.data.Results} + +
  • {postResults.data.Results}
  • +
    )}
    ) }} /> - )} -
    -
    -
    -
    + + +
    + + )} )} From 12f9cd4ec6f696021800d4cbb137d803262cb8d2 Mon Sep 17 00:00:00 2001 From: Chris Hamm <101881895+PremierOneData@users.noreply.github.com> Date: Tue, 7 May 2024 10:23:10 -0500 Subject: [PATCH 25/92] Update TransportRules.jsx Added pre-defined filters --- src/views/email-exchange/transport/TransportRules.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/views/email-exchange/transport/TransportRules.jsx b/src/views/email-exchange/transport/TransportRules.jsx index 4e6f3f68a35d..9d534e17dee5 100644 --- a/src/views/email-exchange/transport/TransportRules.jsx +++ b/src/views/email-exchange/transport/TransportRules.jsx @@ -131,6 +131,10 @@ const TransportRulesList = () => { } datatable={{ + filterlist: [ + { filterName: 'Enabled rules', filter: 'Complex: State eq Enabled' }, + { filterName: 'Disabled rules', filter: 'Complex: State eq Disabled' }, + ], reportName: `${tenant?.defaultDomainName}-transport-rules-list`, path: '/api/ListTransportRules', params: { TenantFilter: tenant?.defaultDomainName }, From 8dd4b09c46a460654fecee4e0e4014a8a79a3646 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 7 May 2024 19:20:56 +0200 Subject: [PATCH 26/92] create auditlog schema --- src/data/auditlogschema.json | 80 ++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/data/auditlogschema.json diff --git a/src/data/auditlogschema.json b/src/data/auditlogschema.json new file mode 100644 index 000000000000..617ab687e604 --- /dev/null +++ b/src/data/auditlogschema.json @@ -0,0 +1,80 @@ +{ + "Common": [ + { + "Id": "Combination GUID", + "RecordType": "AuditLogRecordType", + "CreationTime": "Edm.Date", + "Operation": "Edm.String", + "OrganizationId": "Edm.Guid", + "UserType": "UserType", + "UserKey": "Edm.String", + "Workload": "Edm.String", + "ResultStatus": "Edm.String", + "ObjectId": "Edm.String", + "UserId": "Edm.String", + "ClientIP": "Edm.String", + "Scope": "AuditLogScope", + "AppAccessContext": ["AppAccessContext"], + "IPDetectedbyCIPP": "Edm.String", + "Username": "Edm.String", + "CippGeoLocation": "Edm.String" + } + ], + "Exchange": [ + { + "Id": "Combination GUID", + "RecordType": "AuditLogRecordType", + "CreationTime": "Edm.Date", + "Operation": "Edm.String", + "OrganizationId": "Edm.Guid", + "UserType": "UserType", + "UserKey": "Edm.String", + "Workload": "Edm.String", + "ResultStatus": "Edm.String", + "ObjectId": "Edm.String", + "UserId": "Edm.String", + "ClientIP": "Edm.String", + "Scope": "AuditLogScope", + "AppAccessContext": ["AppAccessContext"], + "ModifiedObjectResolvedName": "Edm.String", + "Parameters": ["Common.NameValuePair"], + "ModifiedProperties": ["Common.ModifiedProperty"], + "ExternalAccess": "Edm.Boolean", + "OriginatingServer": "Edm.String", + "OrganizationName": "Edm.String", + "LogonType": "LogonType", + "InternalLogonType": "LogonType", + "MailboxGuid": "Edm.String", + "MailboxOwnerUPN": "Edm.String", + "MailboxOwnerSid": "Edm.String", + "MailboxOwnerMasterAccountSid": "Edm.String", + "LogonUserSid": "Edm.String", + "LogonUserDisplayName": "Edm.String", + "ClientInfoString": "Edm.String", + "ClientIPAddress": "Edm.String", + "ClientMachineName": "Edm.String", + "ClientProcessName": "Edm.String", + "ClientVersion": "Edm.String" + } + ], + "AzureAD": [ + { + "AzureActiveDirectoryEventType": "AzureActiveDirectoryEventType", + "ExtendedProperties": ["Common.NameValuePair"], + "ModifiedProperties": ["Common.ModifiedProperty"], + "Actor": ["IdentityTypeValuePair"], + "ActorContextId": "Edm.String", + "ActorIpAddress": "Edm.String", + "InterSystemsId": "Edm.String", + "IntraSystemsId": "Edm.String", + "SupportTicketId": "Edm.String", + "Target": ["IdentityTypeValuePair"], + "TargetContextId": "Edm.String", + "ApplicationId": "Edm.String", + "Client": "Edm.String", + "DeviceProperties": ["Common.NameValuePair"], + "ErrorCode": "Edm.String", + "LogonError": "Edm.String" + } + ] +} From 55205d20cc8065f7b700c46f7cbd72a97ba26e57 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 7 May 2024 17:49:10 -0400 Subject: [PATCH 27/92] Replace maintenance page with Durable Functions --- src/components/contentcards/CippChartCard.jsx | 24 +- .../cipp/app-settings/SettingsMaintenance.jsx | 274 +++++++++--------- 2 files changed, 156 insertions(+), 142 deletions(-) diff --git a/src/components/contentcards/CippChartCard.jsx b/src/components/contentcards/CippChartCard.jsx index 468282888f5b..3246631c52d2 100644 --- a/src/components/contentcards/CippChartCard.jsx +++ b/src/components/contentcards/CippChartCard.jsx @@ -1,9 +1,10 @@ import React from 'react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { CCard, CCardBody, CCardFooter, CCardHeader, CCardTitle } from '@coreui/react' +import { CButton, CCard, CCardBody, CCardFooter, CCardHeader, CCardTitle } from '@coreui/react' import Skeleton from 'react-loading-skeleton' import { CChart } from '@coreui/react-chartjs' import { getStyle } from '@coreui/utils' +import PropTypes from 'prop-types' export default function CippChartCard({ title, @@ -13,12 +14,22 @@ export default function CippChartCard({ ChartType = 'pie', LegendLocation = 'bottom', isFetching, + refreshFunction, }) { return ( {titleType === 'big' ?

    {title}

    : title} + {refreshFunction && ( + + + + )}
    @@ -30,6 +41,7 @@ export default function CippChartCard({ labels: ChartLabels, datasets: [ { + label: title, backgroundColor: [ getStyle('--cyberdrain-warning'), getStyle('--cyberdrain-info'), @@ -59,3 +71,13 @@ export default function CippChartCard({
    ) } +CippChartCard.propTypes = { + title: PropTypes.string.isRequired, + titleType: PropTypes.oneOf(['normal', 'big']), + ChartData: PropTypes.array.isRequired, + ChartLabels: PropTypes.array.isRequired, + ChartType: PropTypes.oneOf(['pie', 'bar', 'line']), + LegendLocation: PropTypes.oneOf(['top', 'bottom', 'left', 'right']), + isFetching: PropTypes.bool, + refreshFunction: PropTypes.func, +} diff --git a/src/views/cipp/app-settings/SettingsMaintenance.jsx b/src/views/cipp/app-settings/SettingsMaintenance.jsx index d7387f849400..9279fd5843fc 100644 --- a/src/views/cipp/app-settings/SettingsMaintenance.jsx +++ b/src/views/cipp/app-settings/SettingsMaintenance.jsx @@ -1,22 +1,13 @@ import React, { useState } from 'react' -import { useLazyGenericGetRequestQuery } from 'src/store/api/app.js' -import { - CButton, - CCard, - CCardBody, - CCardHeader, - CCardTitle, - CCol, - CForm, - CRow, -} from '@coreui/react' -import { Form } from 'react-final-form' -import Skeleton from 'react-loading-skeleton' -import { RFFCFormSelect } from 'src/components/forms/index.js' +import { useGenericGetRequestQuery, useLazyGenericGetRequestQuery } from 'src/store/api/app.js' +import { CButton, CCallout, CCol, CRow, CSpinner } from '@coreui/react' +import CippChartCard from 'src/components/contentcards/CippChartCard' +import { CippDatatable, CippTable, cellDateFormatter } from 'src/components/tables' +import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' +import { CippCallout, CippContentCard } from 'src/components/layout' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faLink, faScroll } from '@fortawesome/free-solid-svg-icons' -import { CippCodeBlock } from 'src/components/utilities/index.js' -import { Buffer } from 'buffer' +import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import { ModalService } from 'src/components/utilities' /** * Performs maintenance operations on settings. @@ -24,138 +15,139 @@ import { Buffer } from 'buffer' * @returns {JSX.Element} The JSX element representing the settings maintenance component. */ export function SettingsMaintenance() { - const [selectedScript, setSelectedScript] = useState() - const [listBackend, listBackendResult] = useLazyGenericGetRequestQuery() - const [listScript, listScriptResult] = useLazyGenericGetRequestQuery() - const [listScriptLink, listScriptLinkResult] = useLazyGenericGetRequestQuery() + const orchestrators = useGenericGetRequestQuery({ + path: '/api/ExecDurableFunctions', + params: { Action: 'ListOrchestrators' }, + }) + const durableStats = useGenericGetRequestQuery({ + path: '/api/ExecDurableFunctions', + params: { Action: 'ListStats' }, + }) - const handleSubmit = async (values) => { - listScript({ path: 'api/ExecMaintenanceScripts', params: values }) - setSelectedScript(values.ScriptFile) - } + const [resetDurables, resetDurableStatus] = useLazyGenericGetRequestQuery() - const handleGetLink = () => { - listScriptLink({ - path: 'api/ExecMaintenanceScripts', - params: { ScriptFile: selectedScript, MakeLink: 'True' }, + const handleResetDurables = () => { + ModalService.confirm({ + title: 'Confirm', + body:
    Are you sure you want to reset all Durable Orchestrators?
    , + onConfirm: () => + resetDurables({ + path: '/api/ExecDurableFunctions', + params: { Action: 'ResetDurables' }, + }).then(() => { + orchestrators.refetch() + durableStats.refetch() + }), + confirmLabel: 'Reset', + cancelLabel: 'Cancel', }) } + + const ResetButton = ( + + Reset Durables + + ) + return ( - <> - {listBackendResult.isUninitialized && listBackend({ path: 'api/ExecMaintenanceScripts' })} - - - - - Maintenance - - - { - return ( - - {listBackendResult.isFetching && ( - <> - - - - - - - )} - {!listBackendResult.isFetching && listBackendResult.isSuccess && ( - <> - - - - - - - - - - Load Script - - - - - )} - - ) - }} - /> - - +
    + + + { + return queue?.Name + })} + ChartData={durableStats.data?.Queues?.map((queue) => { + return queue?.ApproximateMessageCount + })} + isFetching={durableStats.isLoading} + refreshFunction={() => durableStats.refetch()} + /> + + + { + return status.Name + })} + ChartData={durableStats?.data?.Orchestrators?.map((status) => { + return status.Count + })} + isFetching={durableStats.isLoading} + refreshFunction={() => durableStats.refetch()} + /> + + + + +

    Use these actions when troubleshooting performance issues with the backend.

    +

    + NOTE: Resetting durables will terminate any running processes. +

    +
    + + {resetDurableStatus.isFetching && } + {!resetDurableStatus.isFetching && resetDurableStatus.isSuccess && ( + + {resetDurableStatus?.data?.Message} + + )} +
    - - - {listScriptResult.isFetching && ( - - - - - - )} - {!listScriptResult.isFetching && listScriptResult.isSuccess && ( - - - Script Details - - -

    - - - Create Link - -

    - {listScriptLinkResult.isSuccess && ( -

    - {listScriptLinkResult.data.Link !== undefined && ( - <> -

    - Copy this text into a PowerShell terminal, we recommend Azure Cloud Shell. - Azure modules and the az command line utilties are required for these - scripts to work. The link is valid for 5 minutes. -

    - - - )} -

    - )} - {listScriptResult.data.ScriptContent !== undefined && ( -

    -

    Maintenance Script Contents
    - -

    - )} -
    -
    - )} + + + + row['CreatedTime'], + sortable: true, + cell: cellDateFormatter({ format: 'short' }), + }, + { + name: 'Completed', + selector: (row) => row?.CompletedTime, + sortable: true, + cell: cellDateFormatter({ format: 'short' }), + }, + { + name: 'Name', + selector: (row) => row['Name'], + sortable: true, + cell: cellGenericFormatter(), + }, + { + name: 'Status', + selector: (row) => row['RuntimeStatus'], + sortable: true, + cell: cellGenericFormatter(), + }, + { + name: 'Input', + selector: (row) => row['Input'], + cell: cellGenericFormatter(), + }, + ]} + filterlist={[ + { filterName: 'Running', filter: 'Complex: RuntimeStatus eq Running' }, + { filterName: 'Pending', filter: 'Complex: RuntimeStatus eq Pending' }, + { filterName: 'Completed', filter: 'Complex: RuntimeStatus eq Completed' }, + { filterName: 'Failed', filter: 'Complex: RuntimeStatus eq Failed' }, + ]} + isFetching={orchestrators.isFetching} + refreshFunction={() => orchestrators.refetch()} + /> + - +
    ) } From 36762be89a3498671e039d91dd8c413ef204688c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 8 May 2024 00:57:07 +0200 Subject: [PATCH 28/92] base setup for new alerting --- src/data/auditlogschema.json | 952 ++++++++++++++++-- .../tenant/administration/AlertWizard.jsx | 166 ++- 2 files changed, 1004 insertions(+), 114 deletions(-) diff --git a/src/data/auditlogschema.json b/src/data/auditlogschema.json index 617ab687e604..7e0054b18aa3 100644 --- a/src/data/auditlogschema.json +++ b/src/data/auditlogschema.json @@ -1,80 +1,884 @@ { - "Common": [ - { - "Id": "Combination GUID", - "RecordType": "AuditLogRecordType", - "CreationTime": "Edm.Date", - "Operation": "Edm.String", - "OrganizationId": "Edm.Guid", - "UserType": "UserType", - "UserKey": "Edm.String", - "Workload": "Edm.String", - "ResultStatus": "Edm.String", - "ObjectId": "Edm.String", - "UserId": "Edm.String", - "ClientIP": "Edm.String", - "Scope": "AuditLogScope", - "AppAccessContext": ["AppAccessContext"], - "IPDetectedbyCIPP": "Edm.String", - "Username": "Edm.String", - "CippGeoLocation": "Edm.String" - } + "Common": { + "Id": "String", + "RecordType": "List:AuditLogRecordType", + "CreationTime": "String", + "Operation": "String", + "OrganizationId": "String", + "UserType": "List:UserType", + "UserKey": "String", + "Workload": "String", + "ResultStatus": "String", + "ObjectId": "String", + "UserId": "String", + "ClientIP": "String", + "IPDetectedbyCIPP": "String", + "Username": "String", + "CIPPGeoLocation": "List:countryList", + "CIPPBadRepIP": "String", + "CIPPHostedIP": "String" + }, + "Audit.Exchange": { + "Id": "Combination GUID", + "RecordType": "List:AuditLogRecordType", + "CreationTime": "String", + "Operation": "String", + "OrganizationId": "Guid", + "UserType": "List:UserType", + "UserKey": "String", + "Workload": "String", + "ResultStatus": "String", + "ObjectId": "String", + "UserId": "String", + "ClientIP": "String", + "Scope": "List:AuditLogScope", + "ModifiedObjectResolvedname": "String", + "Parameters": "Common.namevaluePair", + "ExternalAccess": "Boolean", + "OriginatingServer": "String", + "Organizationname": "String", + "LogonType": "LogonType", + "InternalLogonType": "List:LogonType", + "MailboxGuid": "String", + "MailboxOwnerUPN": "String", + "MailboxOwnerSid": "String", + "MailboxOwnerMasterAccountSid": "String", + "LogonUserSid": "String", + "LogonUserDisplayname": "String", + "ClientInfoString": "String", + "ClientIPAddress": "String", + "ClientMachinename": "String", + "ClientProcessname": "String", + "ClientVersion": "String" + }, + "Audit.AzureActiveDirectory": { + "AzureActiveDirectoryEventType": "List:AzureActiveDirectoryEventType", + "ExtendedProperties": "Common.namevaluePair", + "ModifiedProperties": "Common.ModifiedProperty", + "Actor": "List:IdentityTypevaluePair", + "ActorContextId": "String", + "ActorIpAddress": "String", + "InterSystemsId": "String", + "IntraSystemsId": "String", + "SupportTicketId": "String", + "Target": "List:IdentityTypevaluePair", + "TargetContextId": "String", + "ApplicationId": "String", + "Client": "String", + "Errorvalue": "String", + "LogonError": "String" + }, + "List:LogonType": [ + { "value": 0, "Membername": "Owner", "name": "The mailbox owner." }, + { + "value": 1, + "Membername": "Admin", + "name": "A person with administrative privileges for someone's mailbox." + }, + { + "value": 2, + "Membername": "Delegated", + "name": "A person with delegate privileges for someone's mailbox." + }, + { + "value": 3, + "Membername": "Transport", + "name": "A transport service in the Microsoft datacenter." + }, + { + "value": 4, + "Membername": "SystemService", + "name": "A service account in the Microsoft datacenter" + }, + { "value": 5, "Membername": "BestAccess", "name": "Reserved for internal use." }, + { "value": 6, "Membername": "DelegatedAdmin", "name": "A delegated administrator." } ], - "Exchange": [ - { - "Id": "Combination GUID", - "RecordType": "AuditLogRecordType", - "CreationTime": "Edm.Date", - "Operation": "Edm.String", - "OrganizationId": "Edm.Guid", - "UserType": "UserType", - "UserKey": "Edm.String", - "Workload": "Edm.String", - "ResultStatus": "Edm.String", - "ObjectId": "Edm.String", - "UserId": "Edm.String", - "ClientIP": "Edm.String", - "Scope": "AuditLogScope", - "AppAccessContext": ["AppAccessContext"], - "ModifiedObjectResolvedName": "Edm.String", - "Parameters": ["Common.NameValuePair"], - "ModifiedProperties": ["Common.ModifiedProperty"], - "ExternalAccess": "Edm.Boolean", - "OriginatingServer": "Edm.String", - "OrganizationName": "Edm.String", - "LogonType": "LogonType", - "InternalLogonType": "LogonType", - "MailboxGuid": "Edm.String", - "MailboxOwnerUPN": "Edm.String", - "MailboxOwnerSid": "Edm.String", - "MailboxOwnerMasterAccountSid": "Edm.String", - "LogonUserSid": "Edm.String", - "LogonUserDisplayName": "Edm.String", - "ClientInfoString": "Edm.String", - "ClientIPAddress": "Edm.String", - "ClientMachineName": "Edm.String", - "ClientProcessName": "Edm.String", - "ClientVersion": "Edm.String" - } + "List:UserType": [ + { "value": 0, "Membername": "Regular", "name": "A regular user." }, + { "value": 1, "Membername": "Reserved", "name": "A reserved user." }, + { "value": 2, "Membername": "Admin", "name": "An administrator." }, + { "value": 3, "Membername": "DcAdmin", "name": "A Microsoft datacenter operator." }, + { "value": 4, "Membername": "System", "name": "A system account." }, + { "value": 5, "Membername": "Application", "name": "An application." }, + { "value": 6, "Membername": "ServicePrincipal", "name": "A service principal." }, + { "value": 7, "Membername": "CustomPolicy", "name": "A custom policy." }, + { "value": 8, "Membername": "SystemPolicy", "name": "A system policy." } ], - "AzureAD": [ - { - "AzureActiveDirectoryEventType": "AzureActiveDirectoryEventType", - "ExtendedProperties": ["Common.NameValuePair"], - "ModifiedProperties": ["Common.ModifiedProperty"], - "Actor": ["IdentityTypeValuePair"], - "ActorContextId": "Edm.String", - "ActorIpAddress": "Edm.String", - "InterSystemsId": "Edm.String", - "IntraSystemsId": "Edm.String", - "SupportTicketId": "Edm.String", - "Target": ["IdentityTypeValuePair"], - "TargetContextId": "Edm.String", - "ApplicationId": "Edm.String", - "Client": "Edm.String", - "DeviceProperties": ["Common.NameValuePair"], - "ErrorCode": "Edm.String", - "LogonError": "Edm.String" + "List:AuditLogRecordType": [ + { + "value": 1, + "Membername": "ExchangeAdmin", + "name": "Events from the Exchange admin audit log." + }, + { + "value": 2, + "Membername": "ExchangeItem", + "name": "Events from an Exchange mailbox audit log for actions that are performed on a single item, such as creating or receiving an email message." + }, + { + "value": 3, + "Membername": "ExchangeItemGroup", + "name": "Events from an Exchange mailbox audit log for actions that can be performed on multiple items, such as moving or deleted one or more email messages." + }, + { "value": 4, "Membername": "SharePoint", "name": "SharePoint events." }, + { + "value": 6, + "Membername": "SharePointFileOperation", + "name": "SharePoint file operation events." + }, + { "value": 7, "Membername": "OneDrive", "name": "OneDrive for Business events." }, + { + "value": 8, + "Membername": "AzureActiveDirectory", + "name": "Microsoft Entra ID events." + }, + { + "value": 9, + "Membername": "AzureActiveDirectoryAccountLogon", + "name": "Microsoft Entra ID OrgId logon events (deprecated)." + }, + { + "value": 10, + "Membername": "DataCenterSecurityCmdlet", + "name": "Data Center security cmdlet events." + }, + { + "value": 11, + "Membername": "ComplianceDLPSharePoint", + "name": "Data loss protection (DLP) events in SharePoint and OneDrive for Business." + }, + { + "value": 13, + "Membername": "ComplianceDLPExchange", + "name": "Data loss protection (DLP) events in Exchange, when configured via Unified DLP Policy. DLP events based on Exchange Transport Rules are not supported." + }, + { + "value": 14, + "Membername": "SharePointSharingOperation", + "name": "SharePoint sharing events." + }, + { + "value": 15, + "Membername": "AzureActiveDirectoryStsLogon", + "name": "Secure Token Service (STS) logon events in Microsoft Entra ID." + }, + { + "value": 16, + "Membername": "SkypeForBusinessPSTNUsage", + "name": "Public Switched Telephone Network (PSTN) events from Skype for Business." + }, + { + "value": 17, + "Membername": "SkypeForBusinessUsersBlocked", + "name": "Blocked user events from Skype for Business." + }, + { + "value": 18, + "Membername": "SecurityComplianceCenterEOPCmdlet", + "name": "Admin actions from the Security & Compliance Center." + }, + { + "value": 19, + "Membername": "ExchangeAggregatedOperation", + "name": "Aggregated Exchange mailbox auditing events." + }, + { "value": 20, "Membername": "PowerBIAudit", "name": "Power BI events." }, + { "value": 21, "Membername": "CRM", "name": "Dynamics 365 events." }, + { "value": 22, "Membername": "Yammer", "name": "Yammer events." }, + { + "value": 23, + "Membername": "SkypeForBusinessCmdlets", + "name": "Skype for Business events." + }, + { + "value": 24, + "Membername": "Discovery", + "name": "Events for eDiscovery activities performed by running content searches and managing eDiscovery cases in the Security & Compliance Center." + }, + { "value": 25, "Membername": "MicrosoftTeams", "name": "Events from Microsoft Teams." }, + { + "value": 28, + "Membername": "ThreatIntelligence", + "name": "Phishing and malware events from Exchange Online Protection and Microsoft Defender for Office 365." + }, + { + "value": 29, + "Membername": "MailSubmission", + "name": "Submission events from Exchange Online Protection and Microsoft Defender for Office 365." + }, + { + "value": 30, + "Membername": "MicrosoftFlow", + "name": "Microsoft Power Automate (formerly called Microsoft Flow) events." + }, + { "value": 31, "Membername": "AeD", "name": "Advanced eDiscovery events." }, + { "value": 32, "Membername": "MicrosoftStream", "name": "Microsoft Stream events." }, + { + "value": 33, + "Membername": "ComplianceDLPSharePointClassification", + "name": "Events related to DLP classification in SharePoint." + }, + { + "value": 34, + "Membername": "ThreatFinder", + "name": "Campaign-related events from Microsoft Defender for Office 365." + }, + { "value": 35, "Membername": "Project", "name": "Microsoft Project events." }, + { + "value": 36, + "Membername": "SharePointListOperation", + "name": "SharePoint List events." + }, + { + "value": 37, + "Membername": "SharePointCommentOperation", + "name": "SharePoint comment events." + }, + { + "value": 38, + "Membername": "DataGovernance", + "name": "Events related to retention policies and retention labels in the Security & Compliance Center" + }, + { "value": 39, "Membername": "Kaizala", "name": "Kaizala events." }, + { + "value": 40, + "Membername": "SecurityComplianceAlerts", + "name": "Security and compliance alert signals." + }, + { + "value": 41, + "Membername": "ThreatIntelligenceUrl", + "name": "Safe links time-of-block and block override events from Microsoft Defender for Office 365." + }, + { + "value": 42, + "Membername": "SecurityComplianceInsights", + "name": "Events related to insights and reports in the Office 365 security and compliance center." + }, + { + "value": 43, + "Membername": "MIPLabel", + "name": "Events related to the detection in the Transport pipeline of email messages that have been tagged (manually or automatically) with sensitivity labels." + }, + { + "value": 44, + "Membername": "WorkplaceAnalytics", + "name": "Workplace Analytics events." + }, + { "value": 45, "Membername": "PowerAppsApp", "name": "Power Apps events." }, + { + "value": 46, + "Membername": "PowerAppsPlan", + "name": "Subscription plan events for Power Apps." + }, + { + "value": 47, + "Membername": "ThreatIntelligenceAtpContent", + "name": "Phishing and malware events for files in SharePoint, OneDrive for Business, and Microsoft Teams from Microsoft Defender for Office 365." + }, + { + "value": 48, + "Membername": "LabelContentExplorer", + "name": "Events related to data classification content explorer." + }, + { + "value": 49, + "Membername": "TeamsHealthcare", + "name": "Events related to the Patients application in Microsoft Teams for Healthcare." + }, + { + "value": 50, + "Membername": "ExchangeItemAggregated", + "name": "Events related to the MailItemsAccessed mailbox auditing action." + }, + { + "value": 51, + "Membername": "HygieneEvent", + "name": "Events related to outbound spam protection." + }, + { + "value": 52, + "Membername": "DataInsightsRestApiAudit", + "name": "Data Insights REST API events." + }, + { + "value": 53, + "Membername": "InformationBarrierPolicyApplication", + "name": "Events related to the application of information barrier policies." + }, + { + "value": 54, + "Membername": "SharePointListItemOperation", + "name": "SharePoint list item events." + }, + { + "value": 55, + "Membername": "SharePointContentTypeOperation", + "name": "SharePoint list content type events." + }, + { + "value": 56, + "Membername": "SharePointFieldOperation", + "name": "SharePoint list field events." + }, + { "value": 57, "Membername": "MicrosoftTeamsAdmin", "name": "Teams admin events." }, + { + "value": 58, + "Membername": "HRSignal", + "name": "Events related to HR data signals that support the Insider risk management solution." + }, + { "value": 59, "Membername": "MicrosoftTeamsDevice", "name": "Teams device events." }, + { + "value": 60, + "Membername": "MicrosoftTeamsAnalytics", + "name": "Teams analytics events." + }, + { + "value": 61, + "Membername": "InformationWorkerProtection", + "name": "Events related to compromised user alerts." + }, + { + "value": 62, + "Membername": "Campaign", + "name": "Email campaign events from Microsoft Defender for Office 365." + }, + { "value": 63, "Membername": "DLPEndpoint", "name": "Endpoint DLP events." }, + { + "value": 64, + "Membername": "AirInvestigation", + "name": "Automated incident response (AIR) events." + }, + { "value": 65, "Membername": "Quarantine", "name": "Quarantine events." }, + { "value": 66, "Membername": "MicrosoftForms", "name": "Microsoft Forms events." }, + { "value": 67, "Membername": "ApplicationAudit", "name": "Application audit events." }, + { + "value": 68, + "Membername": "ComplianceSupervisionExchange", + "name": "Events tracked by the Communication compliance offensive language model." + }, + { + "value": 69, + "Membername": "CustomerKeyServiceEncryption", + "name": "Events related to the customer key encryption service." + }, + { + "value": 70, + "Membername": "OfficeNative", + "name": "Events related to sensitivity labels applied to Office documents." + }, + { + "value": 71, + "Membername": "MipAutoLabelSharePointItem", + "name": "Auto-labeling events in SharePoint." + }, + { + "value": 72, + "Membername": "MipAutoLabelSharePointPolicyLocation", + "name": "Auto-labeling policy events in SharePoint." + }, + { "value": 73, "Membername": "MicrosoftTeamsShifts", "name": "Teams Shifts events." }, + { + "value": 75, + "Membername": "MipAutoLabelExchangeItem", + "name": "Auto-labeling events in Exchange." + }, + { "value": 76, "Membername": "CortanaBriefing", "name": "Briefing email events." }, + { + "value": 78, + "Membername": "WDATPAlerts", + "name": "Events related to alerts generated by Windows Defender for Endpoint." + }, + { + "value": 82, + "Membername": "SensitivityLabelPolicyMatch", + "name": "Events generated when the file labeled with a sensitivity label is opened or renamed." + }, + { + "value": 83, + "Membername": "SensitivityLabelAction", + "name": "Event generated when sensitivity labels are applied, upStringd, or removed from a file." + }, + { + "value": 84, + "Membername": "SensitivityLabeledFileAction", + "name": "Events generated when a file labeled with a sensitivity label is opened or renamed." + }, + { + "value": 85, + "Membername": "AttackSim", + "name": "Events related to user activities in Attack Simulation & Training in Microsoft Defender for Office 365." + }, + { + "value": 86, + "Membername": "AirManualInvestigation", + "name": "Events related to manual investigations in Automated investigation and response (AIR)." + }, + { + "value": 87, + "Membername": "SecurityComplianceRBAC", + "name": "Security and compliance RBAC events." + }, + { + "value": 88, + "Membername": "UserTraining", + "name": "Events related to user training in Attack Simulation & Training in Microsoft Defender for Office 365." + }, + { + "value": 89, + "Membername": "AirAdminActionInvestigation", + "name": "Events related to admin actions in Automated investigation and response (AIR)." + }, + { + "value": 90, + "Membername": "MSTIC", + "name": "Threat intelligence events in Microsoft Defender for Office 365." + }, + { + "value": 91, + "Membername": "PhysicalBadgingSignal", + "name": "Events related to physical badging signals that support the Insider risk management solution." + }, + { "value": 93, "Membername": "AipDiscover", "name": "AIP scanner events" }, + { + "value": 94, + "Membername": "AipSensitivityLabelAction", + "name": "AIP sensitivity label events" + }, + { "value": 95, "Membername": "AipProtectionAction", "name": "AIP protection events" }, + { "value": 96, "Membername": "AipFileDeleted", "name": "AIP file deletion events" }, + { "value": 97, "Membername": "AipHeartBeat", "name": "AIP heartbeat events" }, + { + "value": 98, + "Membername": "MCASAlerts", + "name": "Events corresponding to alerts triggered by Microsoft Cloud App Security." + }, + { + "value": 99, + "Membername": "OnPremisesFileShareScannerDlp", + "name": "Events related to scanning for sensitive data on file shares." + }, + { + "value": 100, + "Membername": "OnPremisesSharePointScannerDlp", + "name": "Events related to scanning for sensitive data in SharePoint." + }, + { + "value": 101, + "Membername": "ExchangeSearch", + "name": "Events related to using Outlook on the web (OWA) to search for mailbox items." + }, + { + "value": 102, + "Membername": "SharePointSearch", + "name": "Events related to searching an organization's SharePoint home site." + }, + { "value": 103, "Membername": "PrivacyInsights", "name": "Privacy insight events." }, + { "value": 105, "Membername": "MyAnalyticsSettings", "name": "MyAnalytics events." }, + { + "value": 106, + "Membername": "SecurityComplianceUserChange", + "name": "Events related to modifying or deleting a user." + }, + { + "value": 107, + "Membername": "ComplianceDLPExchangeClassification", + "name": "Exchange DLP classification events." + }, + { + "value": 109, + "Membername": "MipExactDataMatch", + "name": "Exact Data Match (EDM) classification events." + }, + { + "value": 113, + "Membername": "MS365DCustomDetection", + "name": "Events related to custom detection actions in Microsoft 365 Defender." + }, + { + "value": 147, + "Membername": "CoreReportingSettings", + "name": "Reports settings events." + }, + { + "value": 148, + "Membername": "ComplianceConnector", + "name": "Events related to importing non-Microsoft data using data connectors in the Microsoft Purview compliance portal." + }, + { + "value": 154, + "Membername": "OMEPortal", + "name": "Encrypted message portal event logs generated by external recipients." + }, + { + "value": 174, + "Membername": "DataShareOperation", + "name": "Events related to sharing of data ingested via SystemSync." + }, + { + "value": 181, + "Membername": "EduDataLakeDownloadOperation", + "name": "Events related to the export of SystemSync ingested data from the lake." + }, + { + "value": 183, + "Membername": "MicrosoftGraphDataConnectOperation", + "name": "Events related to extractions done by Microsoft Graph Data Connect." + }, + { + "value": 186, + "Membername": "PowerPagesSite", + "name": "Activities related to Power Pages site." + }, + { "value": 188, "Membername": "PlannerPlan", "name": "Microsoft Planner plan events." }, + { + "value": 189, + "Membername": "PlannerCopyPlan", + "name": "Microsoft Planner copy plan events." + }, + { "value": 190, "Membername": "PlannerTask", "name": "Microsoft Planner task events." }, + { + "value": 191, + "Membername": "PlannerRoster", + "name": "Microsoft Planner roster and roster membership events." + }, + { + "value": 192, + "Membername": "PlannerPlanList", + "name": "Microsoft Planner plan list events." + }, + { + "value": 193, + "Membername": "PlannerTaskList", + "name": "Microsoft Planner task list events." + }, + { + "value": 194, + "Membername": "PlannerTenantSettings", + "name": "Microsoft Planner tenant settings events." + }, + { + "value": 195, + "Membername": "ProjectForThewebProject", + "name": "Microsoft Project for the web project events." + }, + { + "value": 196, + "Membername": "ProjectForThewebTask", + "name": "Microsoft Project for the web task events." + }, + { + "value": 197, + "Membername": "ProjectForThewebRoadmap", + "name": "Microsoft Project for the web roadmap events." + }, + { + "value": 198, + "Membername": "ProjectForThewebRoadmapItem", + "name": "Microsoft Project for the web roadmap item events." + }, + { + "value": 199, + "Membername": "ProjectForThewebProjectSettings", + "name": "Microsoft Project for the web project tenant settings events." + }, + { + "value": 200, + "Membername": "ProjectForThewebRoadmapSettings", + "name": "Microsoft Project for the web roadmap tenant settings events." + }, + { "value": 216, "Membername": "Viva Goals", "name": "Viva Goals events." }, + { + "value": 217, + "Membername": "MicrosoftGraphDataConnectConsent", + "name": "Events for consent actions performed by tenant admins for Microsoft Graph Data Connect applications." + }, + { + "value": 218, + "Membername": "AttackSimAdmin", + "name": "Events related to admin activities in Attack Simulation & Training in Microsoft Defender for Office 365." + }, + { "value": 230, "Membername": "TeamsUpStrings", "name": "Teams UpStrings App Events." }, + { + "value": 231, + "Membername": "PlannerRosterSensitivityLabel", + "name": "Microsoft Planner roster sensitivity label events." + }, + { + "value": 237, + "Membername": "DefenderExpertsforXDRAdmin", + "name": "Microsoft Defender Experts Administrator action events." + }, + { + "value": 251, + "Membername": "VfamCreatePolicy", + "name": "Viva Access Management policy create events." + }, + { + "value": 252, + "Membername": "VfamUpStringPolicy", + "name": "Viva Access Management policy upString events." + }, + { + "value": 253, + "Membername": "VfamDeletePolicy", + "name": "Viva Access Management policy delete events." + }, + { + "value": 261, + "Membername": "CopilotInteraction", + "name": "Copilot interaction events." } + ], + "List:countryList": [ + { "value": "AF", "name": "Afghanistan" }, + { "value": "AX", "name": "\u00c5land Islands" }, + { "value": "AL", "name": "Albania" }, + { "value": "DZ", "name": "Algeria" }, + { "value": "AS", "name": "American Samoa" }, + { "value": "AD", "name": "Andorra" }, + { "value": "AO", "name": "Angola" }, + { "value": "AI", "name": "Anguilla" }, + { "value": "AQ", "name": "Antarctica" }, + { "value": "AG", "name": "Antigua and Barbuda" }, + { "value": "AR", "name": "Argentina" }, + { "value": "AM", "name": "Armenia" }, + { "value": "AW", "name": "Aruba" }, + { "value": "AU", "name": "Australia" }, + { "value": "AT", "name": "Austria" }, + { "value": "AZ", "name": "Azerbaijan" }, + { "value": "BS", "name": "Bahamas" }, + { "value": "BH", "name": "Bahrain" }, + { "value": "BD", "name": "Bangladesh" }, + { "value": "BB", "name": "Barbados" }, + { "value": "BY", "name": "Belarus" }, + { "value": "BE", "name": "Belgium" }, + { "value": "BZ", "name": "Belize" }, + { "value": "BJ", "name": "Benin" }, + { "value": "BM", "name": "Bermuda" }, + { "value": "BT", "name": "Bhutan" }, + { "value": "BO", "name": "Bolivia, Plurinational State of" }, + { "value": "BQ", "name": "Bonaire, Sint Eustatius and Saba" }, + { "value": "BA", "name": "Bosnia and Herzegovina" }, + { "value": "BW", "name": "Botswana" }, + { "value": "BV", "name": "Bouvet Island" }, + { "value": "BR", "name": "Brazil" }, + { "value": "IO", "name": "British Indian Ocean Territory" }, + { "value": "BN", "name": "Brunei Darussalam" }, + { "value": "BG", "name": "Bulgaria" }, + { "value": "BF", "name": "Burkina Faso" }, + { "value": "BI", "name": "Burundi" }, + { "value": "KH", "name": "Cambodia" }, + { "value": "CM", "name": "Cameroon" }, + { "value": "CA", "name": "Canada" }, + { "value": "CV", "name": "Cape Verde" }, + { "value": "KY", "name": "Cayman Islands" }, + { "value": "CF", "name": "Central African Republic" }, + { "value": "TD", "name": "Chad" }, + { "value": "CL", "name": "Chile" }, + { "value": "CN", "name": "China" }, + { "value": "CX", "name": "Christmas Island" }, + { "value": "CC", "name": "Cocos (Keeling) Islands" }, + { "value": "CO", "name": "Colombia" }, + { "value": "KM", "name": "Comoros" }, + { "value": "CG", "name": "Congo" }, + { "value": "CD", "name": "Congo, the Democratic Republic of the" }, + { "value": "CK", "name": "Cook Islands" }, + { "value": "CR", "name": "Costa Rica" }, + { "value": "CI", "name": "C\u00f4te d'Ivoire" }, + { "value": "HR", "name": "Croatia" }, + { "value": "CU", "name": "Cuba" }, + { "value": "CW", "name": "Cura\u00e7ao" }, + { "value": "CY", "name": "Cyprus" }, + { "value": "CZ", "name": "Czech Republic" }, + { "value": "DK", "name": "Denmark" }, + { "value": "DJ", "name": "Djibouti" }, + { "value": "DM", "name": "Dominica" }, + { "value": "DO", "name": "Dominican Republic" }, + { "value": "EC", "name": "Ecuador" }, + { "value": "EG", "name": "Egypt" }, + { "value": "SV", "name": "El Salvador" }, + { "value": "GQ", "name": "Equatorial Guinea" }, + { "value": "ER", "name": "Eritrea" }, + { "value": "EE", "name": "Estonia" }, + { "value": "ET", "name": "Ethiopia" }, + { "value": "FK", "name": "Falkland Islands (Malvinas)" }, + { "value": "FO", "name": "Faroe Islands" }, + { "value": "FJ", "name": "Fiji" }, + { "value": "FI", "name": "Finland" }, + { "value": "FR", "name": "France" }, + { "value": "GF", "name": "French Guiana" }, + { "value": "PF", "name": "French Polynesia" }, + { "value": "TF", "name": "French Southern Territories" }, + { "value": "GA", "name": "Gabon" }, + { "value": "GM", "name": "Gambia" }, + { "value": "GE", "name": "Georgia" }, + { "value": "DE", "name": "Germany" }, + { "value": "GH", "name": "Ghana" }, + { "value": "GI", "name": "Gibraltar" }, + { "value": "GR", "name": "Greece" }, + { "value": "GL", "name": "Greenland" }, + { "value": "GD", "name": "Grenada" }, + { "value": "GP", "name": "Guadeloupe" }, + { "value": "GU", "name": "Guam" }, + { "value": "GT", "name": "Guatemala" }, + { "value": "GG", "name": "Guernsey" }, + { "value": "GN", "name": "Guinea" }, + { "value": "GW", "name": "Guinea-Bissau" }, + { "value": "GY", "name": "Guyana" }, + { "value": "HT", "name": "Haiti" }, + { "value": "HM", "name": "Heard Island and McDonald Islands" }, + { "value": "VA", "name": "Holy See (Vatican City State)" }, + { "value": "HN", "name": "Honduras" }, + { "value": "HK", "name": "Hong Kong" }, + { "value": "HU", "name": "Hungary" }, + { "value": "IS", "name": "Iceland" }, + { "value": "IN", "name": "India" }, + { "value": "ID", "name": "Indonesia" }, + { "value": "IR", "name": "Iran, Islamic Republic of" }, + { "value": "IQ", "name": "Iraq" }, + { "value": "IE", "name": "Ireland" }, + { "value": "IM", "name": "Isle of Man" }, + { "value": "IL", "name": "Israel" }, + { "value": "IT", "name": "Italy" }, + { "value": "JM", "name": "Jamaica" }, + { "value": "JP", "name": "Japan" }, + { "value": "JE", "name": "Jersey" }, + { "value": "JO", "name": "Jordan" }, + { "value": "KZ", "name": "Kazakhstan" }, + { "value": "KE", "name": "Kenya" }, + { "value": "KI", "name": "Kiribati" }, + { "value": "KP", "name": "Korea, Democratic People's Republic of" }, + { "value": "KR", "name": "Korea, Republic of" }, + { "value": "KW", "name": "Kuwait" }, + { "value": "KG", "name": "Kyrgyzstan" }, + { "value": "LA", "name": "Lao People's Democratic Republic" }, + { "value": "LV", "name": "Latvia" }, + { "value": "LB", "name": "Lebanon" }, + { "value": "LS", "name": "Lesotho" }, + { "value": "LR", "name": "Liberia" }, + { "value": "LY", "name": "Libya" }, + { "value": "LI", "name": "Liechtenstein" }, + { "value": "LT", "name": "Lithuania" }, + { "value": "LU", "name": "Luxembourg" }, + { "value": "MO", "name": "Macao" }, + { "value": "MK", "name": "Macedonia, the Former Yugoslav Republic of" }, + { "value": "MG", "name": "Madagascar" }, + { "value": "MW", "name": "Malawi" }, + { "value": "MY", "name": "Malaysia" }, + { "value": "MV", "name": "Maldives" }, + { "value": "ML", "name": "Mali" }, + { "value": "MT", "name": "Malta" }, + { "value": "MH", "name": "Marshall Islands" }, + { "value": "MQ", "name": "Martinique" }, + { "value": "MR", "name": "Mauritania" }, + { "value": "MU", "name": "Mauritius" }, + { "value": "YT", "name": "Mayotte" }, + { "value": "MX", "name": "Mexico" }, + { "value": "FM", "name": "Micronesia, Federated States of" }, + { "value": "MD", "name": "Moldova, Republic of" }, + { "value": "MC", "name": "Monaco" }, + { "value": "MN", "name": "Mongolia" }, + { "value": "ME", "name": "Montenegro" }, + { "value": "MS", "name": "Montserrat" }, + { "value": "MA", "name": "Morocco" }, + { "value": "MZ", "name": "Mozambique" }, + { "value": "MM", "name": "Myanmar" }, + { "value": "NA", "name": "Namibia" }, + { "value": "NR", "name": "Nauru" }, + { "value": "NP", "name": "Nepal" }, + { "value": "NL", "name": "Netherlands" }, + { "value": "NC", "name": "New Caledonia" }, + { "value": "NZ", "name": "New Zealand" }, + { "value": "NI", "name": "Nicaragua" }, + { "value": "NE", "name": "Niger" }, + { "value": "NG", "name": "Nigeria" }, + { "value": "NU", "name": "Niue" }, + { "value": "NF", "name": "Norfolk Island" }, + { "value": "MP", "name": "Northern Mariana Islands" }, + { "value": "NO", "name": "Norway" }, + { "value": "OM", "name": "Oman" }, + { "value": "PK", "name": "Pakistan" }, + { "value": "PW", "name": "Palau" }, + { "value": "PS", "name": "Palestine, State of" }, + { "value": "PA", "name": "Panama" }, + { "value": "PG", "name": "Papua New Guinea" }, + { "value": "PY", "name": "Paraguay" }, + { "value": "PE", "name": "Peru" }, + { "value": "PH", "name": "Philippines" }, + { "value": "PN", "name": "Pitcairn" }, + { "value": "PL", "name": "Poland" }, + { "value": "PT", "name": "Portugal" }, + { "value": "PR", "name": "Puerto Rico" }, + { "value": "QA", "name": "Qatar" }, + { "value": "RE", "name": "R\u00e9union" }, + { "value": "RO", "name": "Romania" }, + { "value": "RU", "name": "Russian Federation" }, + { "value": "RW", "name": "Rwanda" }, + { "value": "BL", "name": "Saint Barth\u00e9lemy" }, + { "value": "SH", "name": "Saint Helena, Ascension and Tristan da Cunha" }, + { "value": "KN", "name": "Saint Kitts and Nevis" }, + { "value": "LC", "name": "Saint Lucia" }, + { "value": "MF", "name": "Saint Martin (French part)" }, + { "value": "PM", "name": "Saint Pierre and Miquelon" }, + { "value": "VC", "name": "Saint Vincent and the Grenadines" }, + { "value": "WS", "name": "Samoa" }, + { "value": "SM", "name": "San Marino" }, + { "value": "ST", "name": "Sao Tome and Principe" }, + { "value": "SA", "name": "Saudi Arabia" }, + { "value": "SN", "name": "Senegal" }, + { "value": "RS", "name": "Serbia" }, + { "value": "SC", "name": "Seychelles" }, + { "value": "SL", "name": "Sierra Leone" }, + { "value": "SG", "name": "Singapore" }, + { "value": "SX", "name": "Sint Maarten (Dutch part)" }, + { "value": "SK", "name": "Slovakia" }, + { "value": "SI", "name": "Slovenia" }, + { "value": "SB", "name": "Solomon Islands" }, + { "value": "SO", "name": "Somalia" }, + { "value": "ZA", "name": "South Africa" }, + { "value": "GS", "name": "South Georgia and the South Sandwich Islands" }, + { "value": "SS", "name": "South Sudan" }, + { "value": "ES", "name": "Spain" }, + { "value": "LK", "name": "Sri Lanka" }, + { "value": "SD", "name": "Sudan" }, + { "value": "SR", "name": "Suriname" }, + { "value": "SJ", "name": "Svalbard and Jan Mayen" }, + { "value": "SZ", "name": "Swaziland" }, + { "value": "SE", "name": "Sweden" }, + { "value": "CH", "name": "Switzerland" }, + { "value": "SY", "name": "Syrian Arab Republic" }, + { "value": "TW", "name": "Taiwan, Province of China" }, + { "value": "TJ", "name": "Tajikistan" }, + { "value": "TZ", "name": "Tanzania, United Republic of" }, + { "value": "TH", "name": "Thailand" }, + { "value": "TL", "name": "Timor-Leste" }, + { "value": "TG", "name": "Togo" }, + { "value": "TK", "name": "Tokelau" }, + { "value": "TO", "name": "Tonga" }, + { "value": "TT", "name": "Trinidad and Tobago" }, + { "value": "TN", "name": "Tunisia" }, + { "value": "TR", "name": "Turkey" }, + { "value": "TM", "name": "Turkmenistan" }, + { "value": "TC", "name": "Turks and Caicos Islands" }, + { "value": "TV", "name": "Tuvalu" }, + { "value": "UG", "name": "Uganda" }, + { "value": "UA", "name": "Ukraine" }, + { "value": "AE", "name": "United Arab Emirates" }, + { "value": "GB", "name": "United Kingdom" }, + { "value": "US", "name": "United States" }, + { "value": "UM", "name": "United States Minor Outlying Islands" }, + { "value": "UY", "name": "Uruguay" }, + { "value": "UZ", "name": "Uzbekistan" }, + { "value": "VU", "name": "Vanuatu" }, + { "value": "VE", "name": "Venezuela, Bolivarian Republic of" }, + { "value": "VN", "name": "Viet Nam" }, + { "value": "VG", "name": "Virgin Islands, British" }, + { "value": "VI", "name": "Virgin Islands, U.S." }, + { "value": "WF", "name": "Wallis and Futuna" }, + { "value": "EH", "name": "Western Sahara" }, + { "value": "YE", "name": "Yemen" }, + { "value": "ZM", "name": "Zambia" }, + { "value": "ZW", "name": "Zimbabwe" } ] } diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 479bbf018ae1..ca3b8c2db6fd 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react' import { + CBadge, CButton, CCallout, CCard, @@ -20,6 +21,7 @@ import { TenantSelector, TenantSelectorMultiple } from 'src/components/utilities import { Condition, RFFCFormInput, + RFFCFormRadio, RFFCFormSwitch, RFFSelectSearch, } from 'src/components/forms/RFFComponents' @@ -29,6 +31,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import CippButtonCard from 'src/components/contentcards/CippButtonCard' import alertList from 'src/data/alerts.json' +import auditLogSchema from 'src/data/AuditLogSchema.json' const AlertWizard = () => { const dispatch = useDispatch() @@ -135,6 +138,32 @@ const AlertWizard = () => { }, ] + const getAuditLogSchema = (logbook) => { + const common = auditLogSchema.Common + const log = auditLogSchema[logbook] + const combined = { ...common, ...log } + return Object.keys(combined).map((key) => ({ + name: key, + value: combined[key], + })) + } + const [addedEvent, setAddedEvent] = React.useState(1) + + const getAuditLogSchemaList = (objectName, logbook) => { + //get auditLogSchema[logbook][objectName]. return the following object { type: {objectnames value}, data: {if there is a auditLogSchema[logbook][objectnames value], else null} } + console.log(objectName) + console.log(logbook) + const common = auditLogSchema.Common + const log = auditLogSchema[logbook] + const combined = { ...common, ...log } + const object = combined[objectName] + if (object) { + console.log(object) + return { type: object, data: auditLogSchema[logbook][object] } + } + return { type: 'string', data: null } + } + return ( {!queryError && ( @@ -161,7 +190,7 @@ const AlertWizard = () => { {alertType === 'audit' && ( <> - + Select the tenants you want to include in this Alert. @@ -175,7 +204,7 @@ const AlertWizard = () => { return ( - + @@ -200,42 +229,99 @@ const AlertWizard = () => { /> - - - - - - - - - + {addedEvent > 0 && + [...Array(addedEvent)].map((e, i) => ( + + + + AND + + + + + {(props) => { + return ( + + ) + }} + + + + + + + + {(props) => { + return ( + <> + {props.values?.conditions?.[i]?.property?.value === + 'String' && ( + + )} + {props.values?.conditions?.[ + i + ]?.property?.value.startsWith('List:') && ( + + )} + + ) + }} + + + + ))} + + + {addedEvent > 0 && ( + setAddedEvent(addedEvent - 1)} + className={`circular-button`} + title={'-'} + > + + + )} + {addedEvent < 4 && ( + setAddedEvent(addedEvent + 1)} + className={`circular-button`} + title={'+'} + > + + + )} @@ -250,7 +336,7 @@ const AlertWizard = () => { {alertType === 'script' && ( <> - +

    Select the tenants you want to include in this Alert.

    @@ -258,7 +344,7 @@ const AlertWizard = () => {
    - + Date: Wed, 8 May 2024 01:07:13 +0200 Subject: [PATCH 29/92] button added --- .../tenant/administration/AlertWizard.jsx | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index ca3b8c2db6fd..b9ad5cf5c723 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -191,7 +191,7 @@ const AlertWizard = () => { <> - + Select the tenants you want to include in this Alert. @@ -202,10 +202,18 @@ const AlertWizard = () => { initialValues={{ ...initialValues }} render={({ handleSubmit, submitting, values }) => { return ( - + - + + Save Alert + + } + > { <> - +

    Select the tenants you want to include in this Alert.

    @@ -350,7 +358,7 @@ const AlertWizard = () => { titleType="big" CardButton={ - Add Schedule + Save Alert {postResults.isFetching && ( )} From 2debd7bfaa2de1eaabceed81aadcbba09fb9d1e7 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 7 May 2024 20:58:46 -0400 Subject: [PATCH 30/92] Durable maintenance tweaks --- src/components/contentcards/CippChartCard.jsx | 9 ++++++--- src/views/cipp/app-settings/SettingsMaintenance.jsx | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/contentcards/CippChartCard.jsx b/src/components/contentcards/CippChartCard.jsx index 3246631c52d2..3437b629046d 100644 --- a/src/components/contentcards/CippChartCard.jsx +++ b/src/components/contentcards/CippChartCard.jsx @@ -21,7 +21,7 @@ export default function CippChartCard({ {titleType === 'big' ?

    {title}

    : title} - {refreshFunction && ( + {refreshFunction ? ( + ) : ( + + + )}
    - {isFetching && } - {!isFetching && ( + {ChartData.length > 0 && ( { return queue?.ApproximateMessageCount })} - isFetching={durableStats.isLoading} + isFetching={durableStats.isFetching} refreshFunction={() => durableStats.refetch()} />
    @@ -78,7 +78,7 @@ export function SettingsMaintenance() { ChartData={durableStats?.data?.Orchestrators?.map((status) => { return status.Count })} - isFetching={durableStats.isLoading} + isFetching={durableStats.isFetching} refreshFunction={() => durableStats.refetch()} />
    From 60766d69956178002cfac1418accc4d92c72743c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 7 May 2024 21:30:21 -0400 Subject: [PATCH 31/92] Add spin, disable button when fetching --- src/components/contentcards/CippChartCard.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/contentcards/CippChartCard.jsx b/src/components/contentcards/CippChartCard.jsx index 3437b629046d..8ca482ded014 100644 --- a/src/components/contentcards/CippChartCard.jsx +++ b/src/components/contentcards/CippChartCard.jsx @@ -26,8 +26,9 @@ export default function CippChartCard({ className="position-absolute top-0 end-0 mt-2 me-2" variant="ghost" onClick={refreshFunction} + disabled={isFetching} > - + ) : ( @@ -37,7 +38,7 @@ export default function CippChartCard({ - {ChartData.length > 0 && ( + {ChartData && ( Date: Tue, 7 May 2024 22:32:37 -0400 Subject: [PATCH 32/92] Add purge orchestrator option --- src/components/contentcards/CippChartCard.jsx | 3 +- .../cipp/app-settings/SettingsMaintenance.jsx | 38 +++++++++++++++---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/components/contentcards/CippChartCard.jsx b/src/components/contentcards/CippChartCard.jsx index 8ca482ded014..c708ef8e51ad 100644 --- a/src/components/contentcards/CippChartCard.jsx +++ b/src/components/contentcards/CippChartCard.jsx @@ -1,7 +1,6 @@ import React from 'react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { CButton, CCard, CCardBody, CCardFooter, CCardHeader, CCardTitle } from '@coreui/react' -import Skeleton from 'react-loading-skeleton' +import { CButton, CCard, CCardBody, CCardHeader, CCardTitle } from '@coreui/react' import { CChart } from '@coreui/react-chartjs' import { getStyle } from '@coreui/utils' import PropTypes from 'prop-types' diff --git a/src/views/cipp/app-settings/SettingsMaintenance.jsx b/src/views/cipp/app-settings/SettingsMaintenance.jsx index 2e712b8d50e3..d3d73f254759 100644 --- a/src/views/cipp/app-settings/SettingsMaintenance.jsx +++ b/src/views/cipp/app-settings/SettingsMaintenance.jsx @@ -26,14 +26,21 @@ export function SettingsMaintenance() { const [resetDurables, resetDurableStatus] = useLazyGenericGetRequestQuery() - const handleResetDurables = () => { + const handleResetDurables = (action) => { + var actionText = '' + if (action === 'ResetDurables') { + actionText = 'clear Durable Queues? This will stop all queued functions from executing.' + } else if (action === 'PurgeOrchestrators') { + actionText = + 'purge Orchestrator Instances and History? This will also remove the largemessages blob container.' + } ModalService.confirm({ - title: 'Confirm', - body:
    Are you sure you want to reset all Durable Orchestrators?
    , + title: 'Danger Zone', + body:
    Are you sure you want to {actionText}
    , onConfirm: () => resetDurables({ path: '/api/ExecDurableFunctions', - params: { Action: 'ResetDurables' }, + params: { Action: action }, }).then(() => { orchestrators.refetch() durableStats.refetch() @@ -44,9 +51,24 @@ export function SettingsMaintenance() { } const ResetButton = ( - - Reset Durables - + <> + handleResetDurables('ResetDurables')} + color="danger" + className="me-2" + > + Clear Durable Queues + + handleResetDurables('PurgeOrchestrators')} + color="danger" + className="me-2" + > + Purge Orchestrators + + ) return ( @@ -54,7 +76,7 @@ export function SettingsMaintenance() { { From 0ef89101fa537d600ec17dc5fe16b3461fb25bd4 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 7 May 2024 22:41:53 -0400 Subject: [PATCH 33/92] Update AlertWizard.jsx --- src/views/tenant/administration/AlertWizard.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index ca3b8c2db6fd..29fc8625eaf4 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -31,7 +31,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import CippButtonCard from 'src/components/contentcards/CippButtonCard' import alertList from 'src/data/alerts.json' -import auditLogSchema from 'src/data/AuditLogSchema.json' +import auditLogSchema from 'src/data/auditlogschema.json' const AlertWizard = () => { const dispatch = useDispatch() From 69938a1fa75e99295873533c27f789a2c20591f0 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 7 May 2024 22:52:15 -0400 Subject: [PATCH 34/92] Update CippTable.jsx --- src/components/tables/CippTable.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx index 3ba432f63677..e4110f25d152 100644 --- a/src/components/tables/CippTable.jsx +++ b/src/components/tables/CippTable.jsx @@ -614,7 +614,7 @@ export default function CippTable({ className="m-1" size="sm" > - +
    , ]) From 1bfe923fa50ed29b5a5d178851c5830f4ead9b1a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 8 May 2024 11:39:02 +0200 Subject: [PATCH 35/92] updates to wizard --- .../tenant/administration/AlertWizard.jsx | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index acfc39684fc1..96bdbed9ba63 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -14,7 +14,7 @@ import { CWidgetStatsA, } from '@coreui/react' import useQuery from 'src/hooks/useQuery' -import { useDispatch } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { Field, Form, FormSpy } from 'react-final-form' import { CippPage } from 'src/components/layout' import { TenantSelector, TenantSelectorMultiple } from 'src/components/utilities' @@ -31,12 +31,12 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import CippButtonCard from 'src/components/contentcards/CippButtonCard' import alertList from 'src/data/alerts.json' -import auditLogSchema from 'src/data/auditlogschema.json' +import auditLogSchema from 'src/data/AuditLogSchema.json' const AlertWizard = () => { const dispatch = useDispatch() let query = useQuery() - const tenantDomain = query.get('tenantFilter') + const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) const customerId = query.get('customerId') const [queryError, setQueryError] = useState(false) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() @@ -48,15 +48,27 @@ const AlertWizard = () => { isSuccess, } = useListTenantQuery(tenantDomain, customerId) - const onSubmit = (values) => { + const onSubmitScript = (values) => { + const startDate = new Date() + const unixTime = Math.floor(startDate.getTime() / 1000) const shippedValues = { - tenantid: tenantDomain, - displayName: values.displayName, - defaultDomainName: values.defaultDomainName, - customerId: customerId, + TenantFilter: tenantDomain, + Name: `${values.command.label} for ${tenantDomain}`, + Command: { value: `Get-CIPPAlert${values.command.value.name}` }, + Parameters: { input: values.input }, + ScheduledTime: unixTime, + Recurrence: values.Recurrence, + PostExecution: { + Webhook: values.webhook, + Email: values.email, + PSA: values.psa, + }, } - genericPostRequest({ path: '/api/AlertWizard', values: shippedValues }) + genericPostRequest({ path: '/api/AddScheduledItem?hidden=true', values: shippedValues }).then( + (res) => {}, + ) } + const initialValues = { ...tenant[0], } @@ -149,21 +161,6 @@ const AlertWizard = () => { } const [addedEvent, setAddedEvent] = React.useState(1) - const getAuditLogSchemaList = (objectName, logbook) => { - //get auditLogSchema[logbook][objectName]. return the following object { type: {objectnames value}, data: {if there is a auditLogSchema[logbook][objectnames value], else null} } - console.log(objectName) - console.log(logbook) - const common = auditLogSchema.Common - const log = auditLogSchema[logbook] - const combined = { ...common, ...log } - const object = combined[objectName] - if (object) { - console.log(object) - return { type: object, data: auditLogSchema[logbook][object] } - } - return { type: 'string', data: null } - } - return ( {!queryError && ( @@ -198,7 +195,7 @@ const AlertWizard = () => {
    { return ( @@ -347,7 +344,7 @@ const AlertWizard = () => {

    Select the tenants you want to include in this Alert.

    - +
    @@ -366,7 +363,7 @@ const AlertWizard = () => { } > { return ( @@ -392,7 +389,7 @@ const AlertWizard = () => { return ( From 2ef9e4a3152fa2bf591a2fcd13d2d224bb393ee7 Mon Sep 17 00:00:00 2001 From: Esco Date: Fri, 3 May 2024 12:53:06 +0200 Subject: [PATCH 36/92] Added Add New Blocklist Item --- src/importsMap.jsx | 1 + src/routes.json | 6 + .../AddTenantAllowBlockList.jsx | 122 ++++++++++++++++++ .../ListTenantAllowBlockList.jsx | 2 + 4 files changed, 131 insertions(+) create mode 100644 src/views/email-exchange/administration/AddTenantAllowBlockList.jsx diff --git a/src/importsMap.jsx b/src/importsMap.jsx index 36fbf322051d..4f5519498480 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -117,6 +117,7 @@ import React from 'react' "/email/administration/mailbox-rules": React.lazy(() => import('./views/email-exchange/administration/MailboxRuleList')), "/email/administration/Quarantine": React.lazy(() => import('./views/email-exchange/administration/QuarantineList')), "/email/administration/tenant-allow-block-lists": React.lazy(() => import('./views/email-exchange/administration/ListTenantAllowBlockList')), + "/email/administration/add-tenant-allow-block-list": React.lazy(() => import('./views/email-exchange/administration/AddTenantAllowBlockList')), "/email/reports/mailbox-statistics": React.lazy(() => import('./views/email-exchange/reports/MailboxStatisticsList')), "/email/reports/SharedMailboxEnabledAccount": React.lazy(() => import('./views/email-exchange/reports/SharedMailboxEnabledAccount')), "/email/reports/mailbox-cas-settings": React.lazy(() => import('./views/email-exchange/reports/MailboxClientAccessSettingsList')), diff --git a/src/routes.json b/src/routes.json index 0797edb55310..d5a1e79b5ce0 100644 --- a/src/routes.json +++ b/src/routes.json @@ -786,6 +786,12 @@ "component": "views/email-exchange/administration/ListTenantAllowBlockList", "allowedRoles": ["admin", "editor", "readonly"] }, + { + "name": "Add Tenant Allow/Block List", + "path": "/email/administration/add-tenant-allow-block-list", + "component": "views/email-exchange/administration/AddTenantAllowBlockList", + "allowedRoles": ["admin", "editor", "readonly"] + }, { "name": "Email Reports", "path": "/email/reports", diff --git a/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx b/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx new file mode 100644 index 000000000000..9902eb5e8996 --- /dev/null +++ b/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx @@ -0,0 +1,122 @@ +import React from 'react' +import { + CCallout, + CButton, + CCol, + CForm, + CRow, + CSpinner, + CCard, + CCardHeader, + CCardTitle, + CCardBody, +} from '@coreui/react' +import { Form } from 'react-final-form' +import { RFFCFormSelect, RFFCFormInput, RFFCFormCheck } from 'src/components/forms' +import { CippPage } from 'src/components/layout/CippPage' +import { useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { useSelector } from 'react-redux' + +const AddTenantAllowBlockList = () => { + const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) + + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const onSubmit = (values) => { + const shippedValues = { + tenantID: tenantDomain, + entries: values.entries, + listType: values.listType, + notes: values.notes, + listMethod: values.listMethod, + NoExpiration: values.NoExpiration, + } + genericPostRequest({ path: '/api/AddTenantAllowBlockList', values: shippedValues }) + } + return ( + + + + Add Tenant Allow/Block List + + + { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + Add Entry + + + + {postResults.isFetching && ( + + + + )} + {postResults.isSuccess && ( + {postResults.data.Results} + )} + + ) + }} + /> + + + + ) +} + +export default AddTenantAllowBlockList diff --git a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx index 51d6d7ffe50b..1455c064ac2b 100644 --- a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx +++ b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx @@ -6,6 +6,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Link } from 'react-router-dom' import { CippPageList } from 'src/components/layout' import { CellTip } from 'src/components/tables' +import { TitleButton } from 'src/components/buttons' const AllowBlockList = () => { const tenant = useSelector((state) => state.app.currentTenant) @@ -82,6 +83,7 @@ const AllowBlockList = () => { return ( } title="Tenant Allow/Block Lists" datatable={{ columns, From 0b1a58e432e8d72c580e51c0b24ed61a4f1838bb Mon Sep 17 00:00:00 2001 From: Esco Date: Sat, 4 May 2024 00:14:40 +0200 Subject: [PATCH 37/92] Rewrite ListTenantAllowBlockList --- .../ListTenantAllowBlockList.jsx | 175 ++++++++++-------- 1 file changed, 100 insertions(+), 75 deletions(-) diff --git a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx index 1455c064ac2b..15e0b8e5b7ac 100644 --- a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx +++ b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx @@ -1,94 +1,119 @@ -import React from 'react' +import React, { useState } from 'react' import { useSelector } from 'react-redux' import { CButton } from '@coreui/react' -import { faEdit } from '@fortawesome/free-solid-svg-icons' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { Link } from 'react-router-dom' import { CippPageList } from 'src/components/layout' -import { CellTip } from 'src/components/tables' +import { CellTip, cellBooleanFormatter } from 'src/components/tables' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faEdit, faEllipsisV } from '@fortawesome/free-solid-svg-icons' import { TitleButton } from 'src/components/buttons' +import { CippActionsOffcanvas } from 'src/components/utilities' -const AllowBlockList = () => { +const Actions = (row, rowIndex, formatExtraData) => { const tenant = useSelector((state) => state.app.currentTenant) - const Actions = (row, rowIndex, formatExtraData) => ( + const [ocVisible, setOCVisible] = useState(false) + return ( <> - - - - - - - - - - + setOCVisible(true)}> + + + setOCVisible(false)} + /> ) +} + +const columns = [ + { + name: 'Value', + selector: (row) => row['Value'], + sortable: true, + cell: (row) => CellTip(row['Value']), + exportSelector: 'Value', + }, + { + name: 'ListType', + selector: (row) => row['ListType'], + sortable: true, + cell: (row) => CellTip(row['ListType']), + exportSelector: 'ListType', + maxWidth: '80px', + }, + { + name: 'Action', + selector: (row) => row['Action'], + sortable: true, + cell: (row) => CellTip(row['Action']), + exportSelector: 'Action', + maxWidth: '80px', + }, + { + name: 'Notes', + selector: (row) => row['Notes'], + sortable: true, + cell: (row) => CellTip(row['Notes']), + exportSelector: 'Notes', + }, + { + name: 'LastModifiedDateTime', + selector: (row) => row['LastModifiedDateTime'], + sortable: true, + cell: (row) => CellTip(row['LastModifiedDateTime']), + exportSelector: 'LastModifiedDateTime', + }, + { + name: 'ExpirationDate', + selector: (row) => row['ExpirationDate'], + sortable: true, + cell: (row) => CellTip(row['ExpirationDate']), + exportSelector: 'ExpirationDate', + }, + { + name: 'Actions', + cell: Actions, + maxWidth: '80px', + }, +] - const columns = [ - { - name: 'Value', - selector: (row) => row['Value'], - sortable: true, - cell: (row) => CellTip(row['Value']), - exportSelector: 'Value', - }, - { - name: 'ListType', - selector: (row) => row['ListType'], - sortable: true, - cell: (row) => CellTip(row['ListType']), - exportSelector: 'ListType', - maxWidth: '80px', - }, - { - name: 'Action', - selector: (row) => row['Action'], - sortable: true, - cell: (row) => CellTip(row['Action']), - exportSelector: 'Action', - maxWidth: '80px', - }, - { - name: 'Notes', - selector: (row) => row['Notes'], - sortable: true, - cell: (row) => CellTip(row['Notes']), - exportSelector: 'Notes', - }, - { - name: 'LastModifiedDateTime', - selector: (row) => row['LastModifiedDateTime'], - sortable: true, - cell: (row) => CellTip(row['LastModifiedDateTime']), - exportSelector: 'LastModifiedDateTime', - }, - { - name: 'ExpirationDate', - selector: (row) => row['ExpirationDate'], - sortable: true, - cell: (row) => CellTip(row['ExpirationDate']), - exportSelector: 'ExpirationDate', - }, - // { - // name: 'Actions', - // cell: Actions, - // maxWidth: '80px', - // }, - ] +const AllowBlockList = () => { + const tenant = useSelector((state) => state.app.currentTenant) return ( } + titleButton={} title="Tenant Allow/Block Lists" datatable={{ - columns, - path: '/api/ListTenantAllowBlockList', + keyField: 'id', reportName: `${tenant?.defaultDomainName}-TenantAllowBlockList`, + path: '/api/ListTenantAllowBlockList', + columns, params: { TenantFilter: tenant?.defaultDomainName }, }} /> From d82d169eaf712fe995209029a3dd5870bebd3cf8 Mon Sep 17 00:00:00 2001 From: Esco Date: Wed, 8 May 2024 15:33:21 +0200 Subject: [PATCH 38/92] Comment not ready code --- .../administration/ListTenantAllowBlockList.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx index 15e0b8e5b7ac..24bef3e7af7c 100644 --- a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx +++ b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx @@ -95,11 +95,11 @@ const columns = [ cell: (row) => CellTip(row['ExpirationDate']), exportSelector: 'ExpirationDate', }, - { + /*{ name: 'Actions', cell: Actions, maxWidth: '80px', - }, + },*/ ] const AllowBlockList = () => { From a5855bd5f47bd4bd1c3daaad346242ae9f54e99f Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 8 May 2024 15:37:10 -0400 Subject: [PATCH 39/92] Tweaks to Durable Maintenance Adding options for CippActionsOffcanvas for table modal --- src/components/tables/CippTable.jsx | 5 +- .../utilities/CippActionsOffcanvas.jsx | 25 ++++++- .../cipp/app-settings/SettingsMaintenance.jsx | 73 ++++++++++++++++++- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx index e4110f25d152..c977c700cc87 100644 --- a/src/components/tables/CippTable.jsx +++ b/src/components/tables/CippTable.jsx @@ -38,6 +38,7 @@ import { debounce } from 'lodash-es' import { useSearchParams } from 'react-router-dom' import CopyToClipboard from 'react-copy-to-clipboard' import { setDefaultColumns } from 'src/store/features/app' +import { CippCallout } from '../layout' const FilterComponent = ({ filterText, onFilter, onClear, filterlist, onFilterPreset }) => ( <> @@ -888,7 +889,7 @@ export default function CippTable({ {(updatedColumns || !dynamicColumns) && ( <> {(massResults.length >= 1 || loopRunning) && ( - + {massResults[0]?.data?.Metadata?.Heading && ( {massResults.map((message, idx) => { @@ -963,7 +964,7 @@ export default function CippTable({ )} - + )} { const [offcanvasVisible, setOffcanvasVisible] = useState(false) @@ -154,6 +155,28 @@ export default function CippActionsOffcanvas(props) { title: 'Info', size: 'lg', }) + } else if (modalType === 'table') { + const QueryColumns = [] + const columns = Object.keys(modalBody[0]).map((key) => { + QueryColumns.push({ + name: key, + selector: (row) => row[key], + sortable: true, + exportSelector: key, + cell: cellGenericFormatter(), + }) + }) + + ModalService.open({ + data: modalBody, + componentType: 'table', + componentProps: { + columns: QueryColumns, + keyField: 'SKU', + }, + title: 'Info', + size: 'lg', + }) } else { ModalService.confirm({ key: modalContent, @@ -389,7 +412,7 @@ export default function CippActionsOffcanvas(props) { {getResults.isError && ( Could not connect to API: {getResults.error.message} )} - {!cardContent && ( + {!cardContent && props?.extendedInfo && props?.extendedInfo?.length > 0 && ( diff --git a/src/views/cipp/app-settings/SettingsMaintenance.jsx b/src/views/cipp/app-settings/SettingsMaintenance.jsx index d3d73f254759..a65add447d5d 100644 --- a/src/views/cipp/app-settings/SettingsMaintenance.jsx +++ b/src/views/cipp/app-settings/SettingsMaintenance.jsx @@ -7,7 +7,7 @@ import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' import { CippCallout, CippContentCard } from 'src/components/layout' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import CippButtonCard from 'src/components/contentcards/CippButtonCard' -import { ModalService } from 'src/components/utilities' +import { CippActionsOffcanvas, ModalService } from 'src/components/utilities' /** * Performs maintenance operations on settings. @@ -50,6 +50,54 @@ export function SettingsMaintenance() { }) } + const Actions = (row, rowIndex, formatExtraData) => { + const [ocVisible, setOCVisible] = useState(false) + const [getOrchestratorHistory, orchestratorHistory] = useLazyGenericGetRequestQuery() + + function loadOffCanvasDetails(id) { + setOCVisible(true) + getOrchestratorHistory({ + path: 'api/ExecDurableFunctions', + params: { Action: 'ListOrchestratorHistory', PartitionKey: id }, + }) + } + var actions = [ + { + label: 'View History', + color: 'info', + modal: true, + modalType: 'table', + modalBody: orchestratorHistory?.data?.Results ? orchestratorHistory?.data?.Results : '', + }, + { + label: 'Purge Orchestrator', + color: 'danger', + modal: true, + icon: , + modalUrl: `/api/ExecDurableFunctions?Action=PurgeOrchestrators&PartitionKey=${row.PartitionKey}`, + modalMessage: + 'Are you sure you want to purge this orchestrator instance and related history?', + }, + ] + + return ( + <> + loadOffCanvasDetails(row.PartitionKey)}> + + + setOCVisible(false)} + /> + + ) + } + const ResetButton = ( <> , + modalUrl: `/api/ExecDurableFunctions?Action=PurgeOrchestrators&PartitionKey=!PartitionKey`, + modalMessage: + 'Are you sure you want to purge the selected orchestrator instances and related history?', + }, + ], + }} columns={[ { name: 'Created', selector: (row) => row['CreatedTime'], sortable: true, + exportSelector: 'CreatedTime', cell: cellDateFormatter({ format: 'short' }), }, { name: 'Completed', selector: (row) => row?.CompletedTime, sortable: true, + exportSelector: 'CompletedTime', cell: cellDateFormatter({ format: 'short' }), }, { name: 'Name', selector: (row) => row['Name'], sortable: true, + exportSelector: 'Name', cell: cellGenericFormatter(), }, { name: 'Status', selector: (row) => row['RuntimeStatus'], sortable: true, + exportSelector: 'RuntimeStatus', cell: cellGenericFormatter(), }, { @@ -157,6 +223,11 @@ export function SettingsMaintenance() { selector: (row) => row['Input'], cell: cellGenericFormatter(), }, + { + name: 'Actions', + cell: Actions, + maxWidth: '100px', + }, ]} filterlist={[ { filterName: 'Running', filter: 'Complex: RuntimeStatus eq Running' }, From 5cc506033da6477273cb118fa8626b3bf061c44f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 8 May 2024 22:18:33 +0200 Subject: [PATCH 40/92] fix schema --- src/data/{auditlogschema.json => AuditLogSchema.json_1} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/data/{auditlogschema.json => AuditLogSchema.json_1} (100%) diff --git a/src/data/auditlogschema.json b/src/data/AuditLogSchema.json_1 similarity index 100% rename from src/data/auditlogschema.json rename to src/data/AuditLogSchema.json_1 From c95d6fd1616d7150e19dcbec2114189483d8adf0 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 8 May 2024 22:18:46 +0200 Subject: [PATCH 41/92] Fix schema 2 --- src/data/{AuditLogSchema.json_1 => AuditLogSchema.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/data/{AuditLogSchema.json_1 => AuditLogSchema.json} (100%) diff --git a/src/data/AuditLogSchema.json_1 b/src/data/AuditLogSchema.json similarity index 100% rename from src/data/AuditLogSchema.json_1 rename to src/data/AuditLogSchema.json From ba8b02d0e5f7059f930c44a18ad74de7fcff46cc Mon Sep 17 00:00:00 2001 From: Esco Date: Wed, 8 May 2024 19:30:22 +0200 Subject: [PATCH 42/92] Added timezoneList --- src/data/timezoneList.json | 335 +++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 src/data/timezoneList.json diff --git a/src/data/timezoneList.json b/src/data/timezoneList.json new file mode 100644 index 000000000000..d259bc80e65d --- /dev/null +++ b/src/data/timezoneList.json @@ -0,0 +1,335 @@ +[ + { + "timezone": "(UTC-12:00) International Date Line West" + }, + { + "timezone": "(UTC-11:00) Coordinated Universal Time-11" + }, + { + "timezone": "(UTC-10:00) Hawaii" + }, + { + "timezone": "(UTC-09:00) Alaska" + }, + { + "timezone": "(UTC-08:00) Baja California" + }, + { + "timezone": "(UTC-08:00) Pacific Time (US and Canada)" + }, + { + "timezone": "(UTC-07:00) Arizona" + }, + { + "timezone": "(UTC-07:00) Chihuahua, La Paz, Mazatlan" + }, + { + "timezone": "(UTC-07:00) Mountain Time (US and Canada)" + }, + { + "timezone": "(UTC-06:00) Central America" + }, + { + "timezone": "(UTC-06:00) Central Time (US and Canada)" + }, + { + "timezone": "(UTC-06:00) Guadalajara, Mexico City, Monterrey" + }, + { + "timezone": "(UTC-06:00) Saskatchewan" + }, + { + "timezone": "(UTC-05:00) Bogota, Lima, Quito" + }, + { + "timezone": "(UTC-05:00) Eastern Time (US and Canada)" + }, + { + "timezone": "(UTC-05:00) Indiana (East)" + }, + { + "timezone": "(UTC-04:30) Caracas" + }, + { + "timezone": "(UTC-04:00) Asuncion" + }, + { + "timezone": "(UTC-04:00) Atlantic Time (Canada)" + }, + { + "timezone": "(UTC-04:00) Cuiaba" + }, + { + "timezone": "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan" + }, + { + "timezone": "(UTC-04:00) Santiago" + }, + { + "timezone": "(UTC-03:30) Newfoundland" + }, + { + "timezone": "(UTC-03:00) Brasilia" + }, + { + "timezone": "(UTC-03:00) Buenos Aires" + }, + { + "timezone": "(UTC-03:00) Cayenne, Fortaleza" + }, + { + "timezone": "(UTC-03:00) Greenland" + }, + { + "timezone": "(UTC-03:00) Montevideo" + }, + { + "timezone": "(UTC-03:00) Salvador" + }, + { + "timezone": "(UTC-02:00) Coordinated Universal Time-02" + }, + { + "timezone": "(UTC-02:00) Mid-Atlantic" + }, + { + "timezone": "(UTC-01:00) Azores" + }, + { + "timezone": "(UTC-01:00) Cabo Verde" + }, + { + "timezone": "(UTC) Casablanca" + }, + { + "timezone": "(UTC) Coordinated Universal Time" + }, + { + "timezone": "(UTC) Dublin, Edinburgh, Lisbon, London" + }, + { + "timezone": "(UTC) Monrovia, Reykjavik" + }, + { + "timezone": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna" + }, + { + "timezone": "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague" + }, + { + "timezone": "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris" + }, + { + "timezone": "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb" + }, + { + "timezone": "(UTC+01:00) West Central Africa" + }, + { + "timezone": "(UTC+01:00) Windhoek" + }, + { + "timezone": "(UTC+02:00) Amman" + }, + { + "timezone": "(UTC+02:00) Athens, Bucharest" + }, + { + "timezone": "(UTC+02:00) Beirut" + }, + { + "timezone": "(UTC+02:00) Cairo" + }, + { + "timezone": "(UTC+02:00) Damascus" + }, + { + "timezone": "(UTC+02:00) Harare, Pretoria" + }, + { + "timezone": "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius" + }, + { + "timezone": "(UTC+02:00) Jerusalem" + }, + { + "timezone": "(UTC+02:00) Minsk (old)" + }, + { + "timezone": "(UTC+02:00) E. Europe" + }, + { + "timezone": "(UTC+02:00) Kaliningrad" + }, + { + "timezone": "(UTC+03:00) Baghdad" + }, + { + "timezone": "(UTC+03:00) Istanbul" + }, + { + "timezone": "(UTC+03:00) Kuwait, Riyadh" + }, + { + "timezone": "(UTC+03:00) Minsk" + }, + { + "timezone": "(UTC+03:00) Moscow, St. Petersburg, Volgograd" + }, + { + "timezone": "(UTC+03:00) Nairobi" + }, + { + "timezone": "(UTC+03:30) Tehran" + }, + { + "timezone": "(UTC+04:00) Abu Dhabi, Muscat" + }, + { + "timezone": "(UTC+04:00) Astrakhan, Ulyanovsk" + }, + { + "timezone": "(UTC+04:00) Baku" + }, + { + "timezone": "(UTC+04:00) Izhevsk, Samara" + }, + { + "timezone": "(UTC+04:00) Port Louis" + }, + { + "timezone": "(UTC+04:00) Tbilisi" + }, + { + "timezone": "(UTC+04:00) Yerevan" + }, + { + "timezone": "(UTC+04:30) Kabul" + }, + { + "timezone": "(UTC+05:00) Ekaterinburg" + }, + { + "timezone": "(UTC+05:00) Islamabad, Karachi" + }, + { + "timezone": "(UTC+05:00) Tashkent" + }, + { + "timezone": "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi" + }, + { + "timezone": "(UTC+05:30) Sri Jayawardenepura" + }, + { + "timezone": "(UTC+05:45) Kathmandu" + }, + { + "timezone": "(UTC+06:00) Astana" + }, + { + "timezone": "(UTC+06:00) Dhaka" + }, + { + "timezone": "(UTC+06:00) Omsk" + }, + { + "timezone": "(UTC+06:30) Yangon (Rangoon)" + }, + { + "timezone": "(UTC+07:00) Bangkok, Hanoi, Jakarta" + }, + { + "timezone": "(UTC+07:00) Barnaul, Gorno-Altaysk" + }, + { + "timezone": "(UTC+07:00) Krasnoyarsk" + }, + { + "timezone": "(UTC+07:00) Novosibirsk" + }, + { + "timezone": "(UTC+07:00) Tomsk" + }, + { + "timezone": "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi" + }, + { + "timezone": "(UTC+08:00) Irkutsk" + }, + { + "timezone": "(UTC+08:00) Kuala Lumpur, Singapore" + }, + { + "timezone": "(UTC+08:00) Perth" + }, + { + "timezone": "(UTC+08:00) Taipei" + }, + { + "timezone": "(UTC+08:00) Ulaanbaatar" + }, + { + "timezone": "(UTC+09:00) Osaka, Sapporo, Tokyo" + }, + { + "timezone": "(UTC+09:00) Seoul" + }, + { + "timezone": "(UTC+09:00) Yakutsk" + }, + { + "timezone": "(UTC+09:30) Adelaide" + }, + { + "timezone": "(UTC+09:30) Darwin" + }, + { + "timezone": "(UTC+10:00) Brisbane" + }, + { + "timezone": "(UTC+10:00) Canberra, Melbourne, Sydney" + }, + { + "timezone": "(UTC+10:00) Guam, Port Moresby" + }, + { + "timezone": "(UTC+10:00) Hobart" + }, + { + "timezone": "(UTC+10:00) Magadan" + }, + { + "timezone": "(UTC+10:00) Vladivostok" + }, + { + "timezone": "(UTC+11:00) Chokurdakh" + }, + { + "timezone": "(UTC+11:00) Sakhalin" + }, + { + "timezone": "(UTC+11:00) Solomon Is., New Caledonia" + }, + { + "timezone": "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky" + }, + { + "timezone": "(UTC+12:00) Auckland, Wellington" + }, + { + "timezone": "(UTC+12:00) Coordinated Universal Time+12" + }, + { + "timezone": "(UTC+12:00) Fiji" + }, + { + "timezone": "(UTC+12:00) Petropavlovsk-Kamchatsky - Old" + }, + { + "timezone": "(UTC+13:00) Nuku'alofa" + }, + { + "timezone": "(UTC+13:00) Samoa" + } +] From 1929231916c6effb24031a5f3852dba6ec984f38 Mon Sep 17 00:00:00 2001 From: Esco Date: Wed, 8 May 2024 22:29:21 +0200 Subject: [PATCH 43/92] Timezone Selection --- src/data/standards.json | 2 +- src/views/tenant/standards/ListAppliedStandards.jsx | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/data/standards.json b/src/data/standards.json index 8f13c61f5b1f..afb7048f77be 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -1266,7 +1266,7 @@ "helpText": "Sets the default timezone for the tenant. This will be used for all new users and sites.", "addedComponent": [ { - "type": "input", + "type": "TimezoneSelect", "name": "standards.TenantDefaultTimezone.Timezone", "label": "Timezone" } diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index b5c8bc3c8174..3e6ab7fd88b4 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -39,6 +39,7 @@ import { CippTable, cellBooleanFormatter } from 'src/components/tables' import allStandardsList from 'src/data/standards' import CippCodeOffCanvas from 'src/components/utilities/CippCodeOffcanvas' import GDAPRoles from 'src/data/GDAPRoles' +import timezoneList from 'src/data/timezoneList' import Select from 'react-select' import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' @@ -633,6 +634,17 @@ const ApplyNewStandard = () => { }))} /> )} + {component.type === 'TimezoneSelect' && ( + ({ + value: tz.timezone, + name: tz.timezone, + }))} + /> + )} ))}
    From bc20fc025767a29bb88ace6dba1a019b6543ffdd Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 8 May 2024 22:57:41 -0400 Subject: [PATCH 44/92] JIT Admin frontend --- src/_nav.jsx | 5 + src/importsMap.jsx | 283 +++++++++--------- src/routes.json | 6 + .../administration/DeployJITAdmin.jsx | 213 +++++++++++++ 4 files changed, 366 insertions(+), 141 deletions(-) create mode 100644 src/views/identity/administration/DeployJITAdmin.jsx diff --git a/src/_nav.jsx b/src/_nav.jsx index b0ec445ccd13..1454e5afed55 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -75,6 +75,11 @@ const _nav = [ name: 'Roles', to: '/identity/administration/roles', }, + { + component: CNavItem, + name: 'JIT Admin', + to: '/identity/administration/users/jit-admin', + }, { component: CNavItem, name: 'Offboarding Wizard', diff --git a/src/importsMap.jsx b/src/importsMap.jsx index 36fbf322051d..fdf9df74208b 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -1,144 +1,145 @@ import React from 'react' export const importsMap = { - "/home": React.lazy(() => import('./views/home/Home')), - "/cipp/logs": React.lazy(() => import('./views/cipp/Logs')), - "/cipp/scheduler": React.lazy(() => import('./views/cipp/Scheduler')), - "/cipp/statistics": React.lazy(() => import('./views/cipp/Statistics')), - "/cipp/404": React.lazy(() => import('./views/pages/page404/Page404')), - "/cipp/403": React.lazy(() => import('./views/pages/page403/Page403')), - "/cipp/500": React.lazy(() => import('./views/pages/page500/Page500')), - "/identity/administration/users/add": React.lazy(() => import('./views/identity/administration/AddUser')), - "/identity/administration/users/addbulk": React.lazy(() => import('./views/identity/administration/AddUserBulk')), - "/identity/administration/users/edit": React.lazy(() => import('./views/identity/administration/EditUser')), - "/identity/administration/users/view": React.lazy(() => import('./views/identity/administration/ViewUser')), - "/identity/administration/users/InviteGuest": React.lazy(() => import('./views/identity/administration/InviteGuest')), - "/identity/administration/ViewBec": React.lazy(() => import('./views/identity/administration/ViewBEC')), - "/identity/administration/users": React.lazy(() => import('./views/identity/administration/Users')), - "/identity/administration/devices": React.lazy(() => import('./views/identity/administration/Devices')), - "/identity/administration/groups/add": React.lazy(() => import('./views/identity/administration/AddGroup')), - "/identity/administration/group-templates": React.lazy(() => import('./views/identity/administration/GroupTemplates')), - "/identity/administration/group-add-template": React.lazy(() => import('./views/identity/administration/AddGroupTemplate')), - "/identity/administration/deploy-group-template": React.lazy(() => import('./views/identity/administration/DeployGroupTemplate')), - "/identity/administration/groups/edit": React.lazy(() => import('./views/identity/administration/EditGroup')), - "/identity/administration/groups/view": React.lazy(() => import('./views/identity/administration/ViewGroup')), - "/identity/administration/groups": React.lazy(() => import('./views/identity/administration/Groups')), - "/identity/administration/roles": React.lazy(() => import('./views/identity/administration/Roles')), - "/identity/administration/deleted-items": React.lazy(() => import('./views/identity/administration/Deleted')), - "/teams-share/teams/business-voice": React.lazy(() => import('./views/teams-share/teams/BusinessVoice')), - "/identity/administration/offboarding-wizard": React.lazy(() => import('./views/identity/administration/OffboardingWizard')), - "/endpoint/reports/devices": React.lazy(() => import('./views/endpoint/intune/Devices')), - "/identity/reports/mfa-report": React.lazy(() => import('./views/identity/reports/MFAReport')), - "/identity/reports/inactive-users-report": React.lazy(() => import('./views/identity/reports/InactiveUsers')), - "/identity/reports/Signin-report": React.lazy(() => import('./views/identity/reports/SignIns')), - "/identity/reports/azure-ad-connect-report": React.lazy(() => import('./views/identity/reports/AzureADConnectReport')), - "/tenant/administration/tenants": React.lazy(() => import('./views/tenant/administration/Tenants')), - "/tenant/administration/tenants/edit": React.lazy(() => import('./views/tenant/administration/EditTenant')), - "/tenant/administration/partner-relationships": React.lazy(() => import('./views/tenant/administration/PartnerRelationships')), - "/tenant/administration/domains": React.lazy(() => import('./views/tenant/administration/Domains')), - "/tenant/administration/alertswizard": React.lazy(() => import('./views/tenant/administration/AlertWizard')), - "/tenant/administration/alertrules": React.lazy(() => import('./views/tenant/administration/AlertRules')), - "/tenant/administration/alertsqueue": React.lazy(() => import('./views/tenant/administration/ListAlertsQueue')), - "/tenant/administration/graph-explorer": React.lazy(() => import('./views/tenant/administration/GraphExplorer')), - "/tenant/administration/service-health": React.lazy(() => import('./views/tenant/administration/ServiceHealth')), - "/tenant/administration/enterprise-apps": React.lazy(() => import('./views/tenant/administration/ListEnterpriseApps')), - "/tenant/administration/app-consent-requests": React.lazy(() => import('./views/tenant/administration/ListAppConsentRequests')), - "/tenant/conditional/list-policies": React.lazy(() => import('./views/tenant/conditional/ConditionalAccess')), - "/tenant/conditional/deploy-vacation": React.lazy(() => import('./views/tenant/conditional/DeployVacation')), - "/tenant/conditional/test-policy": React.lazy(() => import('./views/tenant/conditional/TestCAPolicy')), - "/tenant/conditional/list-named-locations": React.lazy(() => import('./views/tenant/conditional/NamedLocations')), - "/tenant/conditional/deploy": React.lazy(() => import('./views/tenant/conditional/DeployCA')), - "/tenant/conditional/deploy-named-location": React.lazy(() => import('./views/tenant/conditional/DeployNamedLocation')), - "/tenant/conditional/list-template": React.lazy(() => import('./views/tenant/conditional/ListCATemplates')), - "/tenant/conditional/add-template": React.lazy(() => import('./views/tenant/conditional/AddCATemplate')), - "/tenant/administration/list-licenses": React.lazy(() => import('./views/tenant/administration/ListLicences')), - "/tenant/administration/application-consent": React.lazy(() => import('./views/tenant/administration/ListOauthApps')), - "/tenant/standards/list-applied-standards": React.lazy(() => import('./views/tenant/standards/ListAppliedStandards')), - "/tenant/standards/bpa-report": React.lazy(() => import('./views/tenant/standards/BestPracticeAnalyser')), - "/tenant/standards/domains-analyser": React.lazy(() => import('./views/tenant/standards/DomainsAnalyser')), - "/tenant/standards/individual-domains": React.lazy(() => import('./views/tenant/standards/IndividualDomain')), - "/tenant/administration/tenantlookup": React.lazy(() => import('./views/tenant/administration/TenantLookup')), - "/tenant/tools/geoiplookup": React.lazy(() => import('./views/tenant/administration/GeoIPLookup')), - "/tenant/tools/bpa-report-builder": React.lazy(() => import('./views/tenant/standards/BPAReportBuilder')), - "/tenant/standards/alert-list": React.lazy(() => import('./views/security/incidents/ListAlerts')), - "/endpoint/applications/list": React.lazy(() => import('./views/endpoint/applications/ApplicationsList')), - "/endpoint/applications/queue": React.lazy(() => import('./views/endpoint/applications/ListApplicationQueue')), - "/endpoint/applications/add-choco-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddChocoApp')), - "/endpoint/applications/add-winget-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddWinGet')), - "/endpoint/applications/add-office-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddOffice')), - "/endpoint/applications/add-rmm-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddRMM')), - "/endpoint/autopilot/add-device": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddDevice')), - "/endpoint/autopilot/add-profile": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddProfile')), - "/endpoint/autopilot/add-status-page": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddStatusPage')), - "/endpoint/autopilot/list-devices": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListDevices')), - "/endpoint/autopilot/list-profiles": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListProfiles')), - "/endpoint/autopilot/list-status-pages": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListStatusPages')), - "/endpoint/MEM/list-policies": React.lazy(() => import('./views/endpoint/intune/MEMListPolicies')), - "/endpoint/MEM/list-compliance-policies": React.lazy(() => import('./views/endpoint/intune/MEMListCompliance')), - "/endpoint/MEM/list-appprotection-policies": React.lazy(() => import('./views/endpoint/intune/MEMListAppProtection')), - "/endpoint/MEM/edit-policy": React.lazy(() => import('./views/endpoint/intune/MEMEditPolicy')), - "/endpoint/MEM/ca-policies": React.lazy(() => import('./views/endpoint/intune/MEMCAPolicies')), - "/endpoint/MEM/add-policy": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicy')), - "/endpoint/MEM/add-policy-template": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicyTemplate')), - "/endpoint/MEM/list-templates": React.lazy(() => import('./views/endpoint/intune/MEMListPolicyTemplates')), - "/security/defender/deployment": React.lazy(() => import('./views/security/defender/DeployDefender')), - "/security/defender/list-defender": React.lazy(() => import('./views/security/defender/ListDefender')), - "/security/defender/list-defender-tvm": React.lazy(() => import('./views/security/defender/ListVuln')), - "/teams-share/onedrive/list": React.lazy(() => import('./views/teams-share/onedrive/OneDriveList')), - "/teams-share/sharepoint/list-sharepoint": React.lazy(() => import('./views/teams-share/sharepoint/SharepointList')), - "/teams-share/teams/list-team": React.lazy(() => import('./views/teams-share/teams/TeamsListTeam')), - "/teams-share/teams/view-team-settings": React.lazy(() => import('./views/teams-share/teams/ViewTeamSettings')), - "/teams-share/teams/add-team": React.lazy(() => import('./views/teams-share/teams/TeamsAddTeam')), - "/teams-share/teams/teams-activity": React.lazy(() => import('./views/teams-share/teams/TeamsActivity')), - "/email/administration/contacts": React.lazy(() => import('./views/email-exchange/administration/ContactsList')), - "/email/connectors/list-connectors": React.lazy(() => import('./views/email-exchange/connectors/ConnectorList')), - "/email/connectors/deploy-connector": React.lazy(() => import('./views/email-exchange/connectors/DeployConnector')), - "/email/connectors/add-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/AddConnectorTemplate')), - "/email/connectors/list-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/ListConnectorTemplates')), - "/email/transport/list-rules": React.lazy(() => import('./views/email-exchange/transport/TransportRules')), - "/email/transport/deploy-rules": React.lazy(() => import('./views/email-exchange/transport/DeployTransport')), - "/email/transport/list-templates": React.lazy(() => import('./views/email-exchange/transport/ListTransportTemplates')), - "/email/transport/add-template": React.lazy(() => import('./views/email-exchange/transport/AddTransportTemplate')), - "/email/spamfilter/list-spamfilter": React.lazy(() => import('./views/email-exchange/spamfilter/Spamfilter')), - "/email/spamfilter/deploy": React.lazy(() => import('./views/email-exchange/spamfilter/DeploySpamfilter')), - "/email/spamfilter/list-templates": React.lazy(() => import('./views/email-exchange/spamfilter/ListSpamfilterTemplates')), - "/rooms/management/list-rooms": React.lazy(() => import('./views/rooms/management/ListRooms')), - "/rooms/management/room-lists": React.lazy(() => import('./views/rooms/management/ListRoomLists')), - "/email/tools/mailbox-restore-wizard": React.lazy(() => import('./views/email-exchange/tools/MailboxRestoreWizard')), - "/email/tools/mailbox-restores": React.lazy(() => import('./views/email-exchange/tools/MailboxRestores')), - "/email/tools/mail-test": React.lazy(() => import('./views/email-exchange/tools/MailTest')), - "/email/spamfilter/add-template": React.lazy(() => import('./views/email-exchange/spamfilter/AddSpamfilterTemplate')), - "/email/administration/edit-mailbox-permissions": React.lazy(() => import('./views/email-exchange/administration/EditMailboxPermissions')), - "/email/administration/add-shared-mailbox": React.lazy(() => import('./views/email-exchange/administration/AddSharedMailbox')), - "/email/administration/add-contact": React.lazy(() => import('./views/email-exchange/administration/AddContact')), - "/email/administration/edit-calendar-permissions": React.lazy(() => import('./views/email-exchange/administration/EditCalendarPermissions')), - "/email/administration/view-mobile-devices": React.lazy(() => import('./views/email-exchange/administration/ViewMobileDevices')), - "/email/administration/edit-contact": React.lazy(() => import('./views/email-exchange/administration/EditContact')), - "/email/administration/mailboxes": React.lazy(() => import('./views/email-exchange/administration/MailboxesList')), - "/email/administration/mailbox-rules": React.lazy(() => import('./views/email-exchange/administration/MailboxRuleList')), - "/email/administration/Quarantine": React.lazy(() => import('./views/email-exchange/administration/QuarantineList')), - "/email/administration/tenant-allow-block-lists": React.lazy(() => import('./views/email-exchange/administration/ListTenantAllowBlockList')), - "/email/reports/mailbox-statistics": React.lazy(() => import('./views/email-exchange/reports/MailboxStatisticsList')), - "/email/reports/SharedMailboxEnabledAccount": React.lazy(() => import('./views/email-exchange/reports/SharedMailboxEnabledAccount')), - "/email/reports/mailbox-cas-settings": React.lazy(() => import('./views/email-exchange/reports/MailboxClientAccessSettingsList')), - "/email/reports/message-trace": React.lazy(() => import('./views/email-exchange/reports/MessageTrace')), - "/cipp/user-settings": React.lazy(() => import('./views/cipp/UserSettings')), - "/email/reports/phishing-policies": React.lazy(() => import('./views/email-exchange/reports/PhishingPoliciesList')), - "/security/incidents/list-alerts": React.lazy(() => import('./views/security/incidents/ListAlerts')), - "/security/incidents/list-incidents": React.lazy(() => import('./views/security/incidents/ListIncidents')), - "/security/reports/list-device-compliance": React.lazy(() => import('./views/security/reports/ListDeviceComplianceReport')), - "/license": React.lazy(() => import('./views/pages/license/License')), - "/cipp/settings": React.lazy(() => import('./views/cipp/app-settings/CIPPSettings')), - "/cipp/setup": React.lazy(() => import('./views/cipp/Setup')), - "/tenant/administration/securescore": React.lazy(() => import('./views/tenant/administration/SecureScore')), - "/tenant/administration/gdap": React.lazy(() => import('./views/tenant/administration/GDAPWizard')), - "/tenant/administration/gdap-invite": React.lazy(() => import('./views/tenant/administration/GDAPInviteWizard')), - "/tenant/administration/gdap-role-wizard": React.lazy(() => import('./views/tenant/administration/GDAPRoleWizard')), - "/tenant/administration/gdap-roles": React.lazy(() => import('./views/tenant/administration/ListGDAPRoles')), - "/tenant/administration/gdap-relationships": React.lazy(() => import('././views/tenant/administration/ListGDAPRelationships')), - "/tenant/administration/appapproval": React.lazy(() => import('./views/cipp/AppApproval')), - "/tenant/administration/gdap-status": React.lazy(() => import('./views/tenant/administration/ListGDAPQueue')), - "/tenant/standards/list-standards": React.lazy(() => import('./views/tenant/standards/ListStandards')), - "/tenant/administration/tenant-offboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOffboardingWizard')), - "/tenant/administration/tenant-onboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOnboardingWizard')), + "/home": React.lazy(() => import('./views/home/Home')), + "/cipp/logs": React.lazy(() => import('./views/cipp/Logs')), + "/cipp/scheduler": React.lazy(() => import('./views/cipp/Scheduler')), + "/cipp/statistics": React.lazy(() => import('./views/cipp/Statistics')), + "/cipp/404": React.lazy(() => import('./views/pages/page404/Page404')), + "/cipp/403": React.lazy(() => import('./views/pages/page403/Page403')), + "/cipp/500": React.lazy(() => import('./views/pages/page500/Page500')), + "/identity/administration/users/add": React.lazy(() => import('./views/identity/administration/AddUser')), + "/identity/administration/users/addbulk": React.lazy(() => import('./views/identity/administration/AddUserBulk')), + "/identity/administration/users/edit": React.lazy(() => import('./views/identity/administration/EditUser')), + "/identity/administration/users/view": React.lazy(() => import('./views/identity/administration/ViewUser')), + "/identity/administration/users/InviteGuest": React.lazy(() => import('./views/identity/administration/InviteGuest')), + "/identity/administration/users/jit-admin": React.lazy(() => import('./views/identity/administration/DeployJITAdmin')), + "/identity/administration/ViewBec": React.lazy(() => import('./views/identity/administration/ViewBEC')), + "/identity/administration/users": React.lazy(() => import('./views/identity/administration/Users')), + "/identity/administration/devices": React.lazy(() => import('./views/identity/administration/Devices')), + "/identity/administration/groups/add": React.lazy(() => import('./views/identity/administration/AddGroup')), + "/identity/administration/group-templates": React.lazy(() => import('./views/identity/administration/GroupTemplates')), + "/identity/administration/group-add-template": React.lazy(() => import('./views/identity/administration/AddGroupTemplate')), + "/identity/administration/deploy-group-template": React.lazy(() => import('./views/identity/administration/DeployGroupTemplate')), + "/identity/administration/groups/edit": React.lazy(() => import('./views/identity/administration/EditGroup')), + "/identity/administration/groups/view": React.lazy(() => import('./views/identity/administration/ViewGroup')), + "/identity/administration/groups": React.lazy(() => import('./views/identity/administration/Groups')), + "/identity/administration/roles": React.lazy(() => import('./views/identity/administration/Roles')), + "/identity/administration/deleted-items": React.lazy(() => import('./views/identity/administration/Deleted')), + "/teams-share/teams/business-voice": React.lazy(() => import('./views/teams-share/teams/BusinessVoice')), + "/identity/administration/offboarding-wizard": React.lazy(() => import('./views/identity/administration/OffboardingWizard')), + "/endpoint/reports/devices": React.lazy(() => import('./views/endpoint/intune/Devices')), + "/identity/reports/mfa-report": React.lazy(() => import('./views/identity/reports/MFAReport')), + "/identity/reports/inactive-users-report": React.lazy(() => import('./views/identity/reports/InactiveUsers')), + "/identity/reports/Signin-report": React.lazy(() => import('./views/identity/reports/SignIns')), + "/identity/reports/azure-ad-connect-report": React.lazy(() => import('./views/identity/reports/AzureADConnectReport')), + "/tenant/administration/tenants": React.lazy(() => import('./views/tenant/administration/Tenants')), + "/tenant/administration/tenants/edit": React.lazy(() => import('./views/tenant/administration/EditTenant')), + "/tenant/administration/partner-relationships": React.lazy(() => import('./views/tenant/administration/PartnerRelationships')), + "/tenant/administration/domains": React.lazy(() => import('./views/tenant/administration/Domains')), + "/tenant/administration/alertswizard": React.lazy(() => import('./views/tenant/administration/AlertWizard')), + "/tenant/administration/alertrules": React.lazy(() => import('./views/tenant/administration/AlertRules')), + "/tenant/administration/alertsqueue": React.lazy(() => import('./views/tenant/administration/ListAlertsQueue')), + "/tenant/administration/graph-explorer": React.lazy(() => import('./views/tenant/administration/GraphExplorer')), + "/tenant/administration/service-health": React.lazy(() => import('./views/tenant/administration/ServiceHealth')), + "/tenant/administration/enterprise-apps": React.lazy(() => import('./views/tenant/administration/ListEnterpriseApps')), + "/tenant/administration/app-consent-requests": React.lazy(() => import('./views/tenant/administration/ListAppConsentRequests')), + "/tenant/conditional/list-policies": React.lazy(() => import('./views/tenant/conditional/ConditionalAccess')), + "/tenant/conditional/deploy-vacation": React.lazy(() => import('./views/tenant/conditional/DeployVacation')), + "/tenant/conditional/test-policy": React.lazy(() => import('./views/tenant/conditional/TestCAPolicy')), + "/tenant/conditional/list-named-locations": React.lazy(() => import('./views/tenant/conditional/NamedLocations')), + "/tenant/conditional/deploy": React.lazy(() => import('./views/tenant/conditional/DeployCA')), + "/tenant/conditional/deploy-named-location": React.lazy(() => import('./views/tenant/conditional/DeployNamedLocation')), + "/tenant/conditional/list-template": React.lazy(() => import('./views/tenant/conditional/ListCATemplates')), + "/tenant/conditional/add-template": React.lazy(() => import('./views/tenant/conditional/AddCATemplate')), + "/tenant/administration/list-licenses": React.lazy(() => import('./views/tenant/administration/ListLicences')), + "/tenant/administration/application-consent": React.lazy(() => import('./views/tenant/administration/ListOauthApps')), + "/tenant/standards/list-applied-standards": React.lazy(() => import('./views/tenant/standards/ListAppliedStandards')), + "/tenant/standards/bpa-report": React.lazy(() => import('./views/tenant/standards/BestPracticeAnalyser')), + "/tenant/standards/domains-analyser": React.lazy(() => import('./views/tenant/standards/DomainsAnalyser')), + "/tenant/standards/individual-domains": React.lazy(() => import('./views/tenant/standards/IndividualDomain')), + "/tenant/administration/tenantlookup": React.lazy(() => import('./views/tenant/administration/TenantLookup')), + "/tenant/tools/geoiplookup": React.lazy(() => import('./views/tenant/administration/GeoIPLookup')), + "/tenant/tools/bpa-report-builder": React.lazy(() => import('./views/tenant/standards/BPAReportBuilder')), + "/tenant/standards/alert-list": React.lazy(() => import('./views/security/incidents/ListAlerts')), + "/endpoint/applications/list": React.lazy(() => import('./views/endpoint/applications/ApplicationsList')), + "/endpoint/applications/queue": React.lazy(() => import('./views/endpoint/applications/ListApplicationQueue')), + "/endpoint/applications/add-choco-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddChocoApp')), + "/endpoint/applications/add-winget-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddWinGet')), + "/endpoint/applications/add-office-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddOffice')), + "/endpoint/applications/add-rmm-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddRMM')), + "/endpoint/autopilot/add-device": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddDevice')), + "/endpoint/autopilot/add-profile": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddProfile')), + "/endpoint/autopilot/add-status-page": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddStatusPage')), + "/endpoint/autopilot/list-devices": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListDevices')), + "/endpoint/autopilot/list-profiles": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListProfiles')), + "/endpoint/autopilot/list-status-pages": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListStatusPages')), + "/endpoint/MEM/list-policies": React.lazy(() => import('./views/endpoint/intune/MEMListPolicies')), + "/endpoint/MEM/list-compliance-policies": React.lazy(() => import('./views/endpoint/intune/MEMListCompliance')), + "/endpoint/MEM/list-appprotection-policies": React.lazy(() => import('./views/endpoint/intune/MEMListAppProtection')), + "/endpoint/MEM/edit-policy": React.lazy(() => import('./views/endpoint/intune/MEMEditPolicy')), + "/endpoint/MEM/ca-policies": React.lazy(() => import('./views/endpoint/intune/MEMCAPolicies')), + "/endpoint/MEM/add-policy": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicy')), + "/endpoint/MEM/add-policy-template": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicyTemplate')), + "/endpoint/MEM/list-templates": React.lazy(() => import('./views/endpoint/intune/MEMListPolicyTemplates')), + "/security/defender/deployment": React.lazy(() => import('./views/security/defender/DeployDefender')), + "/security/defender/list-defender": React.lazy(() => import('./views/security/defender/ListDefender')), + "/security/defender/list-defender-tvm": React.lazy(() => import('./views/security/defender/ListVuln')), + "/teams-share/onedrive/list": React.lazy(() => import('./views/teams-share/onedrive/OneDriveList')), + "/teams-share/sharepoint/list-sharepoint": React.lazy(() => import('./views/teams-share/sharepoint/SharepointList')), + "/teams-share/teams/list-team": React.lazy(() => import('./views/teams-share/teams/TeamsListTeam')), + "/teams-share/teams/view-team-settings": React.lazy(() => import('./views/teams-share/teams/ViewTeamSettings')), + "/teams-share/teams/add-team": React.lazy(() => import('./views/teams-share/teams/TeamsAddTeam')), + "/teams-share/teams/teams-activity": React.lazy(() => import('./views/teams-share/teams/TeamsActivity')), + "/email/administration/contacts": React.lazy(() => import('./views/email-exchange/administration/ContactsList')), + "/email/connectors/list-connectors": React.lazy(() => import('./views/email-exchange/connectors/ConnectorList')), + "/email/connectors/deploy-connector": React.lazy(() => import('./views/email-exchange/connectors/DeployConnector')), + "/email/connectors/add-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/AddConnectorTemplate')), + "/email/connectors/list-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/ListConnectorTemplates')), + "/email/transport/list-rules": React.lazy(() => import('./views/email-exchange/transport/TransportRules')), + "/email/transport/deploy-rules": React.lazy(() => import('./views/email-exchange/transport/DeployTransport')), + "/email/transport/list-templates": React.lazy(() => import('./views/email-exchange/transport/ListTransportTemplates')), + "/email/transport/add-template": React.lazy(() => import('./views/email-exchange/transport/AddTransportTemplate')), + "/email/spamfilter/list-spamfilter": React.lazy(() => import('./views/email-exchange/spamfilter/Spamfilter')), + "/email/spamfilter/deploy": React.lazy(() => import('./views/email-exchange/spamfilter/DeploySpamfilter')), + "/email/spamfilter/list-templates": React.lazy(() => import('./views/email-exchange/spamfilter/ListSpamfilterTemplates')), + "/rooms/management/list-rooms": React.lazy(() => import('./views/rooms/management/ListRooms')), + "/rooms/management/room-lists": React.lazy(() => import('./views/rooms/management/ListRoomLists')), + "/email/tools/mailbox-restore-wizard": React.lazy(() => import('./views/email-exchange/tools/MailboxRestoreWizard')), + "/email/tools/mailbox-restores": React.lazy(() => import('./views/email-exchange/tools/MailboxRestores')), + "/email/tools/mail-test": React.lazy(() => import('./views/email-exchange/tools/MailTest')), + "/email/spamfilter/add-template": React.lazy(() => import('./views/email-exchange/spamfilter/AddSpamfilterTemplate')), + "/email/administration/edit-mailbox-permissions": React.lazy(() => import('./views/email-exchange/administration/EditMailboxPermissions')), + "/email/administration/add-shared-mailbox": React.lazy(() => import('./views/email-exchange/administration/AddSharedMailbox')), + "/email/administration/add-contact": React.lazy(() => import('./views/email-exchange/administration/AddContact')), + "/email/administration/edit-calendar-permissions": React.lazy(() => import('./views/email-exchange/administration/EditCalendarPermissions')), + "/email/administration/view-mobile-devices": React.lazy(() => import('./views/email-exchange/administration/ViewMobileDevices')), + "/email/administration/edit-contact": React.lazy(() => import('./views/email-exchange/administration/EditContact')), + "/email/administration/mailboxes": React.lazy(() => import('./views/email-exchange/administration/MailboxesList')), + "/email/administration/mailbox-rules": React.lazy(() => import('./views/email-exchange/administration/MailboxRuleList')), + "/email/administration/Quarantine": React.lazy(() => import('./views/email-exchange/administration/QuarantineList')), + "/email/administration/tenant-allow-block-lists": React.lazy(() => import('./views/email-exchange/administration/ListTenantAllowBlockList')), + "/email/reports/mailbox-statistics": React.lazy(() => import('./views/email-exchange/reports/MailboxStatisticsList')), + "/email/reports/SharedMailboxEnabledAccount": React.lazy(() => import('./views/email-exchange/reports/SharedMailboxEnabledAccount')), + "/email/reports/mailbox-cas-settings": React.lazy(() => import('./views/email-exchange/reports/MailboxClientAccessSettingsList')), + "/email/reports/message-trace": React.lazy(() => import('./views/email-exchange/reports/MessageTrace')), + "/cipp/user-settings": React.lazy(() => import('./views/cipp/UserSettings')), + "/email/reports/phishing-policies": React.lazy(() => import('./views/email-exchange/reports/PhishingPoliciesList')), + "/security/incidents/list-alerts": React.lazy(() => import('./views/security/incidents/ListAlerts')), + "/security/incidents/list-incidents": React.lazy(() => import('./views/security/incidents/ListIncidents')), + "/security/reports/list-device-compliance": React.lazy(() => import('./views/security/reports/ListDeviceComplianceReport')), + "/license": React.lazy(() => import('./views/pages/license/License')), + "/cipp/settings": React.lazy(() => import('./views/cipp/app-settings/CIPPSettings')), + "/cipp/setup": React.lazy(() => import('./views/cipp/Setup')), + "/tenant/administration/securescore": React.lazy(() => import('./views/tenant/administration/SecureScore')), + "/tenant/administration/gdap": React.lazy(() => import('./views/tenant/administration/GDAPWizard')), + "/tenant/administration/gdap-invite": React.lazy(() => import('./views/tenant/administration/GDAPInviteWizard')), + "/tenant/administration/gdap-role-wizard": React.lazy(() => import('./views/tenant/administration/GDAPRoleWizard')), + "/tenant/administration/gdap-roles": React.lazy(() => import('./views/tenant/administration/ListGDAPRoles')), + "/tenant/administration/gdap-relationships": React.lazy(() => import('././views/tenant/administration/ListGDAPRelationships')), + "/tenant/administration/appapproval": React.lazy(() => import('./views/cipp/AppApproval')), + "/tenant/administration/gdap-status": React.lazy(() => import('./views/tenant/administration/ListGDAPQueue')), + "/tenant/standards/list-standards": React.lazy(() => import('./views/tenant/standards/ListStandards')), + "/tenant/administration/tenant-offboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOffboardingWizard')), + "/tenant/administration/tenant-onboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOnboardingWizard')), } -export default importsMap +export default importsMap \ No newline at end of file diff --git a/src/routes.json b/src/routes.json index 0797edb55310..b585c9ff9c93 100644 --- a/src/routes.json +++ b/src/routes.json @@ -76,6 +76,12 @@ "component": "views/identity/administration/InviteGuest", "allowedRoles": ["admin", "editor", "readonly"] }, + { + "path": "/identity/administration/users/jit-admin", + "name": "JIT Admin", + "component": "views/identity/administration/DeployJITAdmin", + "allowedRoles": ["admin", "editor", "readonly"] + }, { "path": "/identity/administration/ViewBec", "name": "View BEC", diff --git a/src/views/identity/administration/DeployJITAdmin.jsx b/src/views/identity/administration/DeployJITAdmin.jsx new file mode 100644 index 000000000000..dfbdf4090964 --- /dev/null +++ b/src/views/identity/administration/DeployJITAdmin.jsx @@ -0,0 +1,213 @@ +import React, { useState } from 'react' +import { CButton, CCallout, CCol, CForm, CRow, CSpinner, CTooltip } from '@coreui/react' +import { useSelector } from 'react-redux' +import { Field, Form, FormSpy } from 'react-final-form' +import { Condition, RFFCFormRadio, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms' +import { + useGenericGetRequestQuery, + useLazyGenericGetRequestQuery, + useLazyGenericPostRequestQuery, +} from 'src/store/api/app' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons' +import { CippContentCard, CippPage, CippPageList } from 'src/components/layout' +import { CellTip } from 'src/components/tables/CellGenericFormat' +import 'react-datepicker/dist/react-datepicker.css' +import { CippActionsOffcanvas, ModalService, TenantSelector } from 'src/components/utilities' +import arrayMutators from 'final-form-arrays' +import DatePicker from 'react-datepicker' +import 'react-datepicker/dist/react-datepicker.css' +import { useListUsersQuery } from 'src/store/api/users' +import { useListConditionalAccessPoliciesQuery } from 'src/store/api/tenants' +import GDAPRoles from 'src/data/GDAPRoles' + +const DeployJITAdmin = () => { + const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery() + const currentDate = new Date() + const [startDate, setStartDate] = useState(currentDate) + const [endDate, setEndDate] = useState(currentDate) + + const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) + const [refreshState, setRefreshState] = useState(false) + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + + const onSubmit = (values) => { + const startTime = Math.floor(startDate.getTime() / 1000) + const endTime = Math.floor(endDate.getTime() / 1000) + const shippedValues = { + tenantFilter: tenantDomain, + UserId: values.UserId?.value, + PolicyId: values.PolicyId?.value, + StartDate: startTime, + EndDate: endTime, + ExpireAction: values?.expireAction ?? 'delete', + } + genericPostRequest({ path: '/api/ExecJITAdmin', values: shippedValues }).then((res) => { + setRefreshState(res.requestId) + }) + } + + const { + data: users = [], + isFetching: usersIsFetching, + error: usersError, + } = useListUsersQuery({ tenantDomain }) + + return ( + + <> + + + + { + return ( + +

    + JIT Admin creates an account that is usable for a specific period of time. + Enter a username, select admin roles, date range and expiration action. +

    + + + + {(props) => } + + + +
    +
    + + + + + + + + + + ({ + value: user.id, + name: `${user.displayName} <${user.userPrincipalName}>`, + }))} + placeholder={!usersIsFetching ? 'Select user' : 'Loading...'} + name="UserId" + isLoading={usersIsFetching} + /> + + + + + ({ + value: role.ObjectId, + name: role.Name, + }))} + multi={true} + placeholder="Select Roles" + name="AdminRoles" + /> + + + + + + setStartDate(date)} + /> + + + + setEndDate(date)} + /> + + + + + + + + + + + Add JIT Admin + {postResults.isFetching && ( + + )} + + + + {postResults.isSuccess && ( + +
  • {postResults.data.Results}
  • +
    + )} + {getResults.isFetching && ( + + Loading + + )} + {getResults.isSuccess && ( + {getResults.data?.Results} + )} + {getResults.isError && ( + + Could not connect to API: {getResults.error.message} + + )} +
    + ) + }} + /> +
    +
    +
    + +
    + ) +} + +export default DeployJITAdmin From eb70d9cacbf19dee0dc6f2ac71c8ca2c033c3d48 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 9 May 2024 13:30:03 +0200 Subject: [PATCH 45/92] classic alerts --- src/views/tenant/administration/AlertWizard.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 96bdbed9ba63..cdebe32a51c7 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -49,8 +49,11 @@ const AlertWizard = () => { } = useListTenantQuery(tenantDomain, customerId) const onSubmitScript = (values) => { + //get current time as startDate, to the closest 15 minutes in the future const startDate = new Date() - const unixTime = Math.floor(startDate.getTime() / 1000) + startDate.setMinutes(startDate.getMinutes() + 15 - (startDate.getMinutes() % 15)) + //unix time, minus a couple of seconds to ensure it runs after the current time + const unixTime = Math.floor(startDate.getTime() / 1000) - 45 const shippedValues = { TenantFilter: tenantDomain, Name: `${values.command.label} for ${tenantDomain}`, From 7845ec5c53ef3e8f7721b29314a83d70477d5573 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 9 May 2024 13:40:11 +0200 Subject: [PATCH 46/92] fix stuff --- src/importsMap.jsx | 284 +++++++++--------- src/routes.json | 4 +- .../ListTenantAllowBlockList.jsx | 4 +- .../rooms}/ListRoomLists.jsx | 0 .../rooms}/ListRooms.jsx | 0 5 files changed, 147 insertions(+), 145 deletions(-) rename src/views/{rooms/management => email-exchange/rooms}/ListRoomLists.jsx (100%) rename src/views/{rooms/management => email-exchange/rooms}/ListRooms.jsx (100%) diff --git a/src/importsMap.jsx b/src/importsMap.jsx index 4f5519498480..7b7589049b42 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -1,145 +1,145 @@ import React from 'react' export const importsMap = { - "/home": React.lazy(() => import('./views/home/Home')), - "/cipp/logs": React.lazy(() => import('./views/cipp/Logs')), - "/cipp/scheduler": React.lazy(() => import('./views/cipp/Scheduler')), - "/cipp/statistics": React.lazy(() => import('./views/cipp/Statistics')), - "/cipp/404": React.lazy(() => import('./views/pages/page404/Page404')), - "/cipp/403": React.lazy(() => import('./views/pages/page403/Page403')), - "/cipp/500": React.lazy(() => import('./views/pages/page500/Page500')), - "/identity/administration/users/add": React.lazy(() => import('./views/identity/administration/AddUser')), - "/identity/administration/users/addbulk": React.lazy(() => import('./views/identity/administration/AddUserBulk')), - "/identity/administration/users/edit": React.lazy(() => import('./views/identity/administration/EditUser')), - "/identity/administration/users/view": React.lazy(() => import('./views/identity/administration/ViewUser')), - "/identity/administration/users/InviteGuest": React.lazy(() => import('./views/identity/administration/InviteGuest')), - "/identity/administration/ViewBec": React.lazy(() => import('./views/identity/administration/ViewBEC')), - "/identity/administration/users": React.lazy(() => import('./views/identity/administration/Users')), - "/identity/administration/devices": React.lazy(() => import('./views/identity/administration/Devices')), - "/identity/administration/groups/add": React.lazy(() => import('./views/identity/administration/AddGroup')), - "/identity/administration/group-templates": React.lazy(() => import('./views/identity/administration/GroupTemplates')), - "/identity/administration/group-add-template": React.lazy(() => import('./views/identity/administration/AddGroupTemplate')), - "/identity/administration/deploy-group-template": React.lazy(() => import('./views/identity/administration/DeployGroupTemplate')), - "/identity/administration/groups/edit": React.lazy(() => import('./views/identity/administration/EditGroup')), - "/identity/administration/groups/view": React.lazy(() => import('./views/identity/administration/ViewGroup')), - "/identity/administration/groups": React.lazy(() => import('./views/identity/administration/Groups')), - "/identity/administration/roles": React.lazy(() => import('./views/identity/administration/Roles')), - "/identity/administration/deleted-items": React.lazy(() => import('./views/identity/administration/Deleted')), - "/teams-share/teams/business-voice": React.lazy(() => import('./views/teams-share/teams/BusinessVoice')), - "/identity/administration/offboarding-wizard": React.lazy(() => import('./views/identity/administration/OffboardingWizard')), - "/endpoint/reports/devices": React.lazy(() => import('./views/endpoint/intune/Devices')), - "/identity/reports/mfa-report": React.lazy(() => import('./views/identity/reports/MFAReport')), - "/identity/reports/inactive-users-report": React.lazy(() => import('./views/identity/reports/InactiveUsers')), - "/identity/reports/Signin-report": React.lazy(() => import('./views/identity/reports/SignIns')), - "/identity/reports/azure-ad-connect-report": React.lazy(() => import('./views/identity/reports/AzureADConnectReport')), - "/tenant/administration/tenants": React.lazy(() => import('./views/tenant/administration/Tenants')), - "/tenant/administration/tenants/edit": React.lazy(() => import('./views/tenant/administration/EditTenant')), - "/tenant/administration/partner-relationships": React.lazy(() => import('./views/tenant/administration/PartnerRelationships')), - "/tenant/administration/domains": React.lazy(() => import('./views/tenant/administration/Domains')), - "/tenant/administration/alertswizard": React.lazy(() => import('./views/tenant/administration/AlertWizard')), - "/tenant/administration/alertrules": React.lazy(() => import('./views/tenant/administration/AlertRules')), - "/tenant/administration/alertsqueue": React.lazy(() => import('./views/tenant/administration/ListAlertsQueue')), - "/tenant/administration/graph-explorer": React.lazy(() => import('./views/tenant/administration/GraphExplorer')), - "/tenant/administration/service-health": React.lazy(() => import('./views/tenant/administration/ServiceHealth')), - "/tenant/administration/enterprise-apps": React.lazy(() => import('./views/tenant/administration/ListEnterpriseApps')), - "/tenant/administration/app-consent-requests": React.lazy(() => import('./views/tenant/administration/ListAppConsentRequests')), - "/tenant/conditional/list-policies": React.lazy(() => import('./views/tenant/conditional/ConditionalAccess')), - "/tenant/conditional/deploy-vacation": React.lazy(() => import('./views/tenant/conditional/DeployVacation')), - "/tenant/conditional/test-policy": React.lazy(() => import('./views/tenant/conditional/TestCAPolicy')), - "/tenant/conditional/list-named-locations": React.lazy(() => import('./views/tenant/conditional/NamedLocations')), - "/tenant/conditional/deploy": React.lazy(() => import('./views/tenant/conditional/DeployCA')), - "/tenant/conditional/deploy-named-location": React.lazy(() => import('./views/tenant/conditional/DeployNamedLocation')), - "/tenant/conditional/list-template": React.lazy(() => import('./views/tenant/conditional/ListCATemplates')), - "/tenant/conditional/add-template": React.lazy(() => import('./views/tenant/conditional/AddCATemplate')), - "/tenant/administration/list-licenses": React.lazy(() => import('./views/tenant/administration/ListLicences')), - "/tenant/administration/application-consent": React.lazy(() => import('./views/tenant/administration/ListOauthApps')), - "/tenant/standards/list-applied-standards": React.lazy(() => import('./views/tenant/standards/ListAppliedStandards')), - "/tenant/standards/bpa-report": React.lazy(() => import('./views/tenant/standards/BestPracticeAnalyser')), - "/tenant/standards/domains-analyser": React.lazy(() => import('./views/tenant/standards/DomainsAnalyser')), - "/tenant/standards/individual-domains": React.lazy(() => import('./views/tenant/standards/IndividualDomain')), - "/tenant/administration/tenantlookup": React.lazy(() => import('./views/tenant/administration/TenantLookup')), - "/tenant/tools/geoiplookup": React.lazy(() => import('./views/tenant/administration/GeoIPLookup')), - "/tenant/tools/bpa-report-builder": React.lazy(() => import('./views/tenant/standards/BPAReportBuilder')), - "/tenant/standards/alert-list": React.lazy(() => import('./views/security/incidents/ListAlerts')), - "/endpoint/applications/list": React.lazy(() => import('./views/endpoint/applications/ApplicationsList')), - "/endpoint/applications/queue": React.lazy(() => import('./views/endpoint/applications/ListApplicationQueue')), - "/endpoint/applications/add-choco-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddChocoApp')), - "/endpoint/applications/add-winget-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddWinGet')), - "/endpoint/applications/add-office-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddOffice')), - "/endpoint/applications/add-rmm-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddRMM')), - "/endpoint/autopilot/add-device": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddDevice')), - "/endpoint/autopilot/add-profile": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddProfile')), - "/endpoint/autopilot/add-status-page": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddStatusPage')), - "/endpoint/autopilot/list-devices": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListDevices')), - "/endpoint/autopilot/list-profiles": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListProfiles')), - "/endpoint/autopilot/list-status-pages": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListStatusPages')), - "/endpoint/MEM/list-policies": React.lazy(() => import('./views/endpoint/intune/MEMListPolicies')), - "/endpoint/MEM/list-compliance-policies": React.lazy(() => import('./views/endpoint/intune/MEMListCompliance')), - "/endpoint/MEM/list-appprotection-policies": React.lazy(() => import('./views/endpoint/intune/MEMListAppProtection')), - "/endpoint/MEM/edit-policy": React.lazy(() => import('./views/endpoint/intune/MEMEditPolicy')), - "/endpoint/MEM/ca-policies": React.lazy(() => import('./views/endpoint/intune/MEMCAPolicies')), - "/endpoint/MEM/add-policy": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicy')), - "/endpoint/MEM/add-policy-template": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicyTemplate')), - "/endpoint/MEM/list-templates": React.lazy(() => import('./views/endpoint/intune/MEMListPolicyTemplates')), - "/security/defender/deployment": React.lazy(() => import('./views/security/defender/DeployDefender')), - "/security/defender/list-defender": React.lazy(() => import('./views/security/defender/ListDefender')), - "/security/defender/list-defender-tvm": React.lazy(() => import('./views/security/defender/ListVuln')), - "/teams-share/onedrive/list": React.lazy(() => import('./views/teams-share/onedrive/OneDriveList')), - "/teams-share/sharepoint/list-sharepoint": React.lazy(() => import('./views/teams-share/sharepoint/SharepointList')), - "/teams-share/teams/list-team": React.lazy(() => import('./views/teams-share/teams/TeamsListTeam')), - "/teams-share/teams/view-team-settings": React.lazy(() => import('./views/teams-share/teams/ViewTeamSettings')), - "/teams-share/teams/add-team": React.lazy(() => import('./views/teams-share/teams/TeamsAddTeam')), - "/teams-share/teams/teams-activity": React.lazy(() => import('./views/teams-share/teams/TeamsActivity')), - "/email/administration/contacts": React.lazy(() => import('./views/email-exchange/administration/ContactsList')), - "/email/connectors/list-connectors": React.lazy(() => import('./views/email-exchange/connectors/ConnectorList')), - "/email/connectors/deploy-connector": React.lazy(() => import('./views/email-exchange/connectors/DeployConnector')), - "/email/connectors/add-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/AddConnectorTemplate')), - "/email/connectors/list-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/ListConnectorTemplates')), - "/email/transport/list-rules": React.lazy(() => import('./views/email-exchange/transport/TransportRules')), - "/email/transport/deploy-rules": React.lazy(() => import('./views/email-exchange/transport/DeployTransport')), - "/email/transport/list-templates": React.lazy(() => import('./views/email-exchange/transport/ListTransportTemplates')), - "/email/transport/add-template": React.lazy(() => import('./views/email-exchange/transport/AddTransportTemplate')), - "/email/spamfilter/list-spamfilter": React.lazy(() => import('./views/email-exchange/spamfilter/Spamfilter')), - "/email/spamfilter/deploy": React.lazy(() => import('./views/email-exchange/spamfilter/DeploySpamfilter')), - "/email/spamfilter/list-templates": React.lazy(() => import('./views/email-exchange/spamfilter/ListSpamfilterTemplates')), - "/rooms/management/list-rooms": React.lazy(() => import('./views/rooms/management/ListRooms')), - "/rooms/management/room-lists": React.lazy(() => import('./views/rooms/management/ListRoomLists')), - "/email/tools/mailbox-restore-wizard": React.lazy(() => import('./views/email-exchange/tools/MailboxRestoreWizard')), - "/email/tools/mailbox-restores": React.lazy(() => import('./views/email-exchange/tools/MailboxRestores')), - "/email/tools/mail-test": React.lazy(() => import('./views/email-exchange/tools/MailTest')), - "/email/spamfilter/add-template": React.lazy(() => import('./views/email-exchange/spamfilter/AddSpamfilterTemplate')), - "/email/administration/edit-mailbox-permissions": React.lazy(() => import('./views/email-exchange/administration/EditMailboxPermissions')), - "/email/administration/add-shared-mailbox": React.lazy(() => import('./views/email-exchange/administration/AddSharedMailbox')), - "/email/administration/add-contact": React.lazy(() => import('./views/email-exchange/administration/AddContact')), - "/email/administration/edit-calendar-permissions": React.lazy(() => import('./views/email-exchange/administration/EditCalendarPermissions')), - "/email/administration/view-mobile-devices": React.lazy(() => import('./views/email-exchange/administration/ViewMobileDevices')), - "/email/administration/edit-contact": React.lazy(() => import('./views/email-exchange/administration/EditContact')), - "/email/administration/mailboxes": React.lazy(() => import('./views/email-exchange/administration/MailboxesList')), - "/email/administration/mailbox-rules": React.lazy(() => import('./views/email-exchange/administration/MailboxRuleList')), - "/email/administration/Quarantine": React.lazy(() => import('./views/email-exchange/administration/QuarantineList')), - "/email/administration/tenant-allow-block-lists": React.lazy(() => import('./views/email-exchange/administration/ListTenantAllowBlockList')), - "/email/administration/add-tenant-allow-block-list": React.lazy(() => import('./views/email-exchange/administration/AddTenantAllowBlockList')), - "/email/reports/mailbox-statistics": React.lazy(() => import('./views/email-exchange/reports/MailboxStatisticsList')), - "/email/reports/SharedMailboxEnabledAccount": React.lazy(() => import('./views/email-exchange/reports/SharedMailboxEnabledAccount')), - "/email/reports/mailbox-cas-settings": React.lazy(() => import('./views/email-exchange/reports/MailboxClientAccessSettingsList')), - "/email/reports/message-trace": React.lazy(() => import('./views/email-exchange/reports/MessageTrace')), - "/cipp/user-settings": React.lazy(() => import('./views/cipp/UserSettings')), - "/email/reports/phishing-policies": React.lazy(() => import('./views/email-exchange/reports/PhishingPoliciesList')), - "/security/incidents/list-alerts": React.lazy(() => import('./views/security/incidents/ListAlerts')), - "/security/incidents/list-incidents": React.lazy(() => import('./views/security/incidents/ListIncidents')), - "/security/reports/list-device-compliance": React.lazy(() => import('./views/security/reports/ListDeviceComplianceReport')), - "/license": React.lazy(() => import('./views/pages/license/License')), - "/cipp/settings": React.lazy(() => import('./views/cipp/app-settings/CIPPSettings')), - "/cipp/setup": React.lazy(() => import('./views/cipp/Setup')), - "/tenant/administration/securescore": React.lazy(() => import('./views/tenant/administration/SecureScore')), - "/tenant/administration/gdap": React.lazy(() => import('./views/tenant/administration/GDAPWizard')), - "/tenant/administration/gdap-invite": React.lazy(() => import('./views/tenant/administration/GDAPInviteWizard')), - "/tenant/administration/gdap-role-wizard": React.lazy(() => import('./views/tenant/administration/GDAPRoleWizard')), - "/tenant/administration/gdap-roles": React.lazy(() => import('./views/tenant/administration/ListGDAPRoles')), - "/tenant/administration/gdap-relationships": React.lazy(() => import('././views/tenant/administration/ListGDAPRelationships')), - "/tenant/administration/appapproval": React.lazy(() => import('./views/cipp/AppApproval')), - "/tenant/administration/gdap-status": React.lazy(() => import('./views/tenant/administration/ListGDAPQueue')), - "/tenant/standards/list-standards": React.lazy(() => import('./views/tenant/standards/ListStandards')), - "/tenant/administration/tenant-offboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOffboardingWizard')), - "/tenant/administration/tenant-onboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOnboardingWizard')), + "/home": React.lazy(() => import('./views/home/Home')), + "/cipp/logs": React.lazy(() => import('./views/cipp/Logs')), + "/cipp/scheduler": React.lazy(() => import('./views/cipp/Scheduler')), + "/cipp/statistics": React.lazy(() => import('./views/cipp/Statistics')), + "/cipp/404": React.lazy(() => import('./views/pages/page404/Page404')), + "/cipp/403": React.lazy(() => import('./views/pages/page403/Page403')), + "/cipp/500": React.lazy(() => import('./views/pages/page500/Page500')), + "/identity/administration/users/add": React.lazy(() => import('./views/identity/administration/AddUser')), + "/identity/administration/users/addbulk": React.lazy(() => import('./views/identity/administration/AddUserBulk')), + "/identity/administration/users/edit": React.lazy(() => import('./views/identity/administration/EditUser')), + "/identity/administration/users/view": React.lazy(() => import('./views/identity/administration/ViewUser')), + "/identity/administration/users/InviteGuest": React.lazy(() => import('./views/identity/administration/InviteGuest')), + "/identity/administration/ViewBec": React.lazy(() => import('./views/identity/administration/ViewBEC')), + "/identity/administration/users": React.lazy(() => import('./views/identity/administration/Users')), + "/identity/administration/devices": React.lazy(() => import('./views/identity/administration/Devices')), + "/identity/administration/groups/add": React.lazy(() => import('./views/identity/administration/AddGroup')), + "/identity/administration/group-templates": React.lazy(() => import('./views/identity/administration/GroupTemplates')), + "/identity/administration/group-add-template": React.lazy(() => import('./views/identity/administration/AddGroupTemplate')), + "/identity/administration/deploy-group-template": React.lazy(() => import('./views/identity/administration/DeployGroupTemplate')), + "/identity/administration/groups/edit": React.lazy(() => import('./views/identity/administration/EditGroup')), + "/identity/administration/groups/view": React.lazy(() => import('./views/identity/administration/ViewGroup')), + "/identity/administration/groups": React.lazy(() => import('./views/identity/administration/Groups')), + "/identity/administration/roles": React.lazy(() => import('./views/identity/administration/Roles')), + "/identity/administration/deleted-items": React.lazy(() => import('./views/identity/administration/Deleted')), + "/teams-share/teams/business-voice": React.lazy(() => import('./views/teams-share/teams/BusinessVoice')), + "/identity/administration/offboarding-wizard": React.lazy(() => import('./views/identity/administration/OffboardingWizard')), + "/endpoint/reports/devices": React.lazy(() => import('./views/endpoint/intune/Devices')), + "/identity/reports/mfa-report": React.lazy(() => import('./views/identity/reports/MFAReport')), + "/identity/reports/inactive-users-report": React.lazy(() => import('./views/identity/reports/InactiveUsers')), + "/identity/reports/Signin-report": React.lazy(() => import('./views/identity/reports/SignIns')), + "/identity/reports/azure-ad-connect-report": React.lazy(() => import('./views/identity/reports/AzureADConnectReport')), + "/tenant/administration/tenants": React.lazy(() => import('./views/tenant/administration/Tenants')), + "/tenant/administration/tenants/edit": React.lazy(() => import('./views/tenant/administration/EditTenant')), + "/tenant/administration/partner-relationships": React.lazy(() => import('./views/tenant/administration/PartnerRelationships')), + "/tenant/administration/domains": React.lazy(() => import('./views/tenant/administration/Domains')), + "/tenant/administration/alertswizard": React.lazy(() => import('./views/tenant/administration/AlertWizard')), + "/tenant/administration/alertrules": React.lazy(() => import('./views/tenant/administration/AlertRules')), + "/tenant/administration/alertsqueue": React.lazy(() => import('./views/tenant/administration/ListAlertsQueue')), + "/tenant/administration/graph-explorer": React.lazy(() => import('./views/tenant/administration/GraphExplorer')), + "/tenant/administration/service-health": React.lazy(() => import('./views/tenant/administration/ServiceHealth')), + "/tenant/administration/enterprise-apps": React.lazy(() => import('./views/tenant/administration/ListEnterpriseApps')), + "/tenant/administration/app-consent-requests": React.lazy(() => import('./views/tenant/administration/ListAppConsentRequests')), + "/tenant/conditional/list-policies": React.lazy(() => import('./views/tenant/conditional/ConditionalAccess')), + "/tenant/conditional/deploy-vacation": React.lazy(() => import('./views/tenant/conditional/DeployVacation')), + "/tenant/conditional/test-policy": React.lazy(() => import('./views/tenant/conditional/TestCAPolicy')), + "/tenant/conditional/list-named-locations": React.lazy(() => import('./views/tenant/conditional/NamedLocations')), + "/tenant/conditional/deploy": React.lazy(() => import('./views/tenant/conditional/DeployCA')), + "/tenant/conditional/deploy-named-location": React.lazy(() => import('./views/tenant/conditional/DeployNamedLocation')), + "/tenant/conditional/list-template": React.lazy(() => import('./views/tenant/conditional/ListCATemplates')), + "/tenant/conditional/add-template": React.lazy(() => import('./views/tenant/conditional/AddCATemplate')), + "/tenant/administration/list-licenses": React.lazy(() => import('./views/tenant/administration/ListLicences')), + "/tenant/administration/application-consent": React.lazy(() => import('./views/tenant/administration/ListOauthApps')), + "/tenant/standards/list-applied-standards": React.lazy(() => import('./views/tenant/standards/ListAppliedStandards')), + "/tenant/standards/bpa-report": React.lazy(() => import('./views/tenant/standards/BestPracticeAnalyser')), + "/tenant/standards/domains-analyser": React.lazy(() => import('./views/tenant/standards/DomainsAnalyser')), + "/tenant/standards/individual-domains": React.lazy(() => import('./views/tenant/standards/IndividualDomain')), + "/tenant/administration/tenantlookup": React.lazy(() => import('./views/tenant/administration/TenantLookup')), + "/tenant/tools/geoiplookup": React.lazy(() => import('./views/tenant/administration/GeoIPLookup')), + "/tenant/tools/bpa-report-builder": React.lazy(() => import('./views/tenant/standards/BPAReportBuilder')), + "/tenant/standards/alert-list": React.lazy(() => import('./views/security/incidents/ListAlerts')), + "/endpoint/applications/list": React.lazy(() => import('./views/endpoint/applications/ApplicationsList')), + "/endpoint/applications/queue": React.lazy(() => import('./views/endpoint/applications/ListApplicationQueue')), + "/endpoint/applications/add-choco-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddChocoApp')), + "/endpoint/applications/add-winget-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddWinGet')), + "/endpoint/applications/add-office-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddOffice')), + "/endpoint/applications/add-rmm-app": React.lazy(() => import('./views/endpoint/applications/ApplicationsAddRMM')), + "/endpoint/autopilot/add-device": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddDevice')), + "/endpoint/autopilot/add-profile": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddProfile')), + "/endpoint/autopilot/add-status-page": React.lazy(() => import('./views/endpoint/autopilot/AutopilotAddStatusPage')), + "/endpoint/autopilot/list-devices": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListDevices')), + "/endpoint/autopilot/list-profiles": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListProfiles')), + "/endpoint/autopilot/list-status-pages": React.lazy(() => import('./views/endpoint/autopilot/AutopilotListStatusPages')), + "/endpoint/MEM/list-policies": React.lazy(() => import('./views/endpoint/intune/MEMListPolicies')), + "/endpoint/MEM/list-compliance-policies": React.lazy(() => import('./views/endpoint/intune/MEMListCompliance')), + "/endpoint/MEM/list-appprotection-policies": React.lazy(() => import('./views/endpoint/intune/MEMListAppProtection')), + "/endpoint/MEM/edit-policy": React.lazy(() => import('./views/endpoint/intune/MEMEditPolicy')), + "/endpoint/MEM/ca-policies": React.lazy(() => import('./views/endpoint/intune/MEMCAPolicies')), + "/endpoint/MEM/add-policy": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicy')), + "/endpoint/MEM/add-policy-template": React.lazy(() => import('./views/endpoint/intune/MEMAddPolicyTemplate')), + "/endpoint/MEM/list-templates": React.lazy(() => import('./views/endpoint/intune/MEMListPolicyTemplates')), + "/security/defender/deployment": React.lazy(() => import('./views/security/defender/DeployDefender')), + "/security/defender/list-defender": React.lazy(() => import('./views/security/defender/ListDefender')), + "/security/defender/list-defender-tvm": React.lazy(() => import('./views/security/defender/ListVuln')), + "/teams-share/onedrive/list": React.lazy(() => import('./views/teams-share/onedrive/OneDriveList')), + "/teams-share/sharepoint/list-sharepoint": React.lazy(() => import('./views/teams-share/sharepoint/SharepointList')), + "/teams-share/teams/list-team": React.lazy(() => import('./views/teams-share/teams/TeamsListTeam')), + "/teams-share/teams/view-team-settings": React.lazy(() => import('./views/teams-share/teams/ViewTeamSettings')), + "/teams-share/teams/add-team": React.lazy(() => import('./views/teams-share/teams/TeamsAddTeam')), + "/teams-share/teams/teams-activity": React.lazy(() => import('./views/teams-share/teams/TeamsActivity')), + "/email/administration/contacts": React.lazy(() => import('./views/email-exchange/administration/ContactsList')), + "/email/connectors/list-connectors": React.lazy(() => import('./views/email-exchange/connectors/ConnectorList')), + "/email/connectors/deploy-connector": React.lazy(() => import('./views/email-exchange/connectors/DeployConnector')), + "/email/connectors/add-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/AddConnectorTemplate')), + "/email/connectors/list-connector-templates": React.lazy(() => import('./views/email-exchange/connectors/ListConnectorTemplates')), + "/email/transport/list-rules": React.lazy(() => import('./views/email-exchange/transport/TransportRules')), + "/email/transport/deploy-rules": React.lazy(() => import('./views/email-exchange/transport/DeployTransport')), + "/email/transport/list-templates": React.lazy(() => import('./views/email-exchange/transport/ListTransportTemplates')), + "/email/transport/add-template": React.lazy(() => import('./views/email-exchange/transport/AddTransportTemplate')), + "/email/spamfilter/list-spamfilter": React.lazy(() => import('./views/email-exchange/spamfilter/Spamfilter')), + "/email/spamfilter/deploy": React.lazy(() => import('./views/email-exchange/spamfilter/DeploySpamfilter')), + "/email/spamfilter/list-templates": React.lazy(() => import('./views/email-exchange/spamfilter/ListSpamfilterTemplates')), + "/rooms/management/list-rooms": React.lazy(() => import('./views/email-exchange/rooms/ListRooms')), + "/rooms/management/room-lists": React.lazy(() => import('./views/email-exchange/rooms/ListRoomLists')), + "/email/tools/mailbox-restore-wizard": React.lazy(() => import('./views/email-exchange/tools/MailboxRestoreWizard')), + "/email/tools/mailbox-restores": React.lazy(() => import('./views/email-exchange/tools/MailboxRestores')), + "/email/tools/mail-test": React.lazy(() => import('./views/email-exchange/tools/MailTest')), + "/email/spamfilter/add-template": React.lazy(() => import('./views/email-exchange/spamfilter/AddSpamfilterTemplate')), + "/email/administration/edit-mailbox-permissions": React.lazy(() => import('./views/email-exchange/administration/EditMailboxPermissions')), + "/email/administration/add-shared-mailbox": React.lazy(() => import('./views/email-exchange/administration/AddSharedMailbox')), + "/email/administration/add-contact": React.lazy(() => import('./views/email-exchange/administration/AddContact')), + "/email/administration/edit-calendar-permissions": React.lazy(() => import('./views/email-exchange/administration/EditCalendarPermissions')), + "/email/administration/view-mobile-devices": React.lazy(() => import('./views/email-exchange/administration/ViewMobileDevices')), + "/email/administration/edit-contact": React.lazy(() => import('./views/email-exchange/administration/EditContact')), + "/email/administration/mailboxes": React.lazy(() => import('./views/email-exchange/administration/MailboxesList')), + "/email/administration/mailbox-rules": React.lazy(() => import('./views/email-exchange/administration/MailboxRuleList')), + "/email/administration/Quarantine": React.lazy(() => import('./views/email-exchange/administration/QuarantineList')), + "/email/administration/tenant-allow-block-lists": React.lazy(() => import('./views/email-exchange/administration/ListTenantAllowBlockList')), + "/email/administration/add-tenant-allow-block-list": React.lazy(() => import('./views/email-exchange/administration/AddTenantAllowBlockList')), + "/email/reports/mailbox-statistics": React.lazy(() => import('./views/email-exchange/reports/MailboxStatisticsList')), + "/email/reports/SharedMailboxEnabledAccount": React.lazy(() => import('./views/email-exchange/reports/SharedMailboxEnabledAccount')), + "/email/reports/mailbox-cas-settings": React.lazy(() => import('./views/email-exchange/reports/MailboxClientAccessSettingsList')), + "/email/reports/message-trace": React.lazy(() => import('./views/email-exchange/reports/MessageTrace')), + "/cipp/user-settings": React.lazy(() => import('./views/cipp/UserSettings')), + "/email/reports/phishing-policies": React.lazy(() => import('./views/email-exchange/reports/PhishingPoliciesList')), + "/security/incidents/list-alerts": React.lazy(() => import('./views/security/incidents/ListAlerts')), + "/security/incidents/list-incidents": React.lazy(() => import('./views/security/incidents/ListIncidents')), + "/security/reports/list-device-compliance": React.lazy(() => import('./views/security/reports/ListDeviceComplianceReport')), + "/license": React.lazy(() => import('./views/pages/license/License')), + "/cipp/settings": React.lazy(() => import('./views/cipp/app-settings/CIPPSettings')), + "/cipp/setup": React.lazy(() => import('./views/cipp/Setup')), + "/tenant/administration/securescore": React.lazy(() => import('./views/tenant/administration/SecureScore')), + "/tenant/administration/gdap": React.lazy(() => import('./views/tenant/administration/GDAPWizard')), + "/tenant/administration/gdap-invite": React.lazy(() => import('./views/tenant/administration/GDAPInviteWizard')), + "/tenant/administration/gdap-role-wizard": React.lazy(() => import('./views/tenant/administration/GDAPRoleWizard')), + "/tenant/administration/gdap-roles": React.lazy(() => import('./views/tenant/administration/ListGDAPRoles')), + "/tenant/administration/gdap-relationships": React.lazy(() => import('././views/tenant/administration/ListGDAPRelationships')), + "/tenant/administration/appapproval": React.lazy(() => import('./views/cipp/AppApproval')), + "/tenant/administration/gdap-status": React.lazy(() => import('./views/tenant/administration/ListGDAPQueue')), + "/tenant/standards/list-standards": React.lazy(() => import('./views/tenant/standards/ListStandards')), + "/tenant/administration/tenant-offboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOffboardingWizard')), + "/tenant/administration/tenant-onboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOnboardingWizard')), } -export default importsMap +export default importsMap \ No newline at end of file diff --git a/src/routes.json b/src/routes.json index d5a1e79b5ce0..e1d382459781 100644 --- a/src/routes.json +++ b/src/routes.json @@ -693,13 +693,13 @@ { "path": "/rooms/management/list-rooms", "name": "Rooms", - "component": "views/rooms/management/ListRooms", + "component": "views/email-exchange/rooms/ListRooms", "allowedRoles": ["admin", "editor", "readonly"] }, { "path": "/rooms/management/room-lists", "name": "Room Lists", - "component": "views/rooms/management/ListRoomLists", + "component": "views/email-exchange/rooms/ListRoomLists", "allowedRoles": ["admin", "editor", "readonly"] }, { diff --git a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx index 24bef3e7af7c..e3a44ab7e7cc 100644 --- a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx +++ b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx @@ -107,7 +107,9 @@ const AllowBlockList = () => { return ( } + titleButton={ + + } title="Tenant Allow/Block Lists" datatable={{ keyField: 'id', diff --git a/src/views/rooms/management/ListRoomLists.jsx b/src/views/email-exchange/rooms/ListRoomLists.jsx similarity index 100% rename from src/views/rooms/management/ListRoomLists.jsx rename to src/views/email-exchange/rooms/ListRoomLists.jsx diff --git a/src/views/rooms/management/ListRooms.jsx b/src/views/email-exchange/rooms/ListRooms.jsx similarity index 100% rename from src/views/rooms/management/ListRooms.jsx rename to src/views/email-exchange/rooms/ListRooms.jsx From 5891171fc30c976fb49e555ee0a893d78bea41b1 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 9 May 2024 13:40:45 +0200 Subject: [PATCH 47/92] fix stuff --- .../AddTenantAllowBlockList.jsx | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx b/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx index 9902eb5e8996..09c48987a730 100644 --- a/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx +++ b/src/views/email-exchange/administration/AddTenantAllowBlockList.jsx @@ -77,16 +77,20 @@ const AddTenantAllowBlockList = () => {
    - + From 974ae6fd3889feb287e8beaf008d3de08e6c3e3c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Thu, 9 May 2024 14:08:03 -0400 Subject: [PATCH 48/92] fix form click issues --- src/components/forms/RFFComponents.jsx | 51 +++++++++++++++++++++++++- src/components/forms/index.js | 2 + 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/components/forms/RFFComponents.jsx b/src/components/forms/RFFComponents.jsx index b3f22f8cda14..737333c7dfc9 100644 --- a/src/components/forms/RFFComponents.jsx +++ b/src/components/forms/RFFComponents.jsx @@ -123,7 +123,9 @@ export const RFFCFormSwitch = ({ >
    (
    { + return ( + <> +
    + {options?.map((option, key) => { + return ( + + {({ input }) => { + return ( + <> + + + ) + }} + + ) + })} +
    + + ) +} + +RFFCFormRadioList.propTypes = { + ...sharedPropTypes, + inline: PropTypes.bool, +} + export const RFFCFormTextarea = ({ name, label, diff --git a/src/components/forms/index.js b/src/components/forms/index.js index 616687f88a0f..00a76ee4554a 100644 --- a/src/components/forms/index.js +++ b/src/components/forms/index.js @@ -5,6 +5,7 @@ import { RFFCFormSwitch, RFFCFormInput, RFFCFormRadio, + RFFCFormRadioList, RFFCFormTextarea, RFFCFormSelect, RFFSelectSearch, @@ -18,6 +19,7 @@ export { RFFCFormSwitch, RFFCFormInput, RFFCFormRadio, + RFFCFormRadioList, RFFCFormTextarea, RFFCFormSelect, RFFSelectSearch, From a8b678cd06dd99442e4304923dc1113b60b12303 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 10 May 2024 12:34:50 +0200 Subject: [PATCH 49/92] fixes securescore bug --- .../tenant/administration/SecureScore.jsx | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/views/tenant/administration/SecureScore.jsx b/src/views/tenant/administration/SecureScore.jsx index 368c2e9ff38e..76c77d584296 100644 --- a/src/views/tenant/administration/SecureScore.jsx +++ b/src/views/tenant/administration/SecureScore.jsx @@ -236,14 +236,20 @@ const SecureScore = () => { title="Compared Score (Similiar sized business)" percentage={ //calculate percentage, round to 1 dec. - Math.round( - (translateData?.averageComparativeScores[1]?.averageScore / - translateData?.maxScore) * - 100 * - 10, - ) / 10 + translateData?.averageComparativeScores + ? Math.round( + (translateData?.averageComparativeScores[1]?.averageScore / + translateData?.maxScore) * + 100 * + 10, + ) / 10 + : 0 + } + topLabel={ + translateData?.averageComparativeScores + ? translateData?.averageComparativeScores[1]?.averageScore + : 0 } - topLabel={translateData?.averageComparativeScores[1]?.averageScore} smallLabel={`of ${translateData?.maxScore} points`} isFetching={isFetching} /> @@ -252,15 +258,20 @@ const SecureScore = () => { From 4cb9fef7ad9ddd32ca8176d734b73711a802f20a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 10 May 2024 12:56:18 +0200 Subject: [PATCH 50/92] added reload after save --- src/views/tenant/standards/ListAppliedStandards.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index 3e6ab7fd88b4..ef06144350ca 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -288,7 +288,7 @@ const ApplyNewStandard = () => { genericPostRequest({ path: '/api/AddStandardsDeploy', values: { ...values.standards, tenant: tenantDomain }, - }) + }).then(() => refetchStandards()) } const [intuneGetRequest, intuneTemplates] = useLazyGenericGetRequestQuery() const [transportGetRequest, transportTemplates] = useLazyGenericGetRequestQuery() @@ -376,7 +376,7 @@ const ApplyNewStandard = () => { } title={`List and edit standard - ${tenantDomain}`} > - {isFetching && } + {isFetching && } {intuneTemplates.isUninitialized && intuneGetRequest({ path: 'api/ListIntuneTemplates' })} {transportTemplates.isUninitialized && From d214ad3162b3fcc5e1274d703a77bf022e51892d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 10 May 2024 13:08:21 +0200 Subject: [PATCH 51/92] moved boxes over card. --- .../tenant/standards/ListAppliedStandards.jsx | 123 +++++++++--------- 1 file changed, 60 insertions(+), 63 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index ef06144350ca..81c20f247c79 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -368,6 +368,66 @@ const ApplyNewStandard = () => { {getResults.error.message} )} + + + 0 + ? Math.round((enabledWarningsCount / totalAvailableStandards) * 1000) / 10 + : 0, + }} + text={ + listStandardResults.length > 0 && listStandardResults[0].appliedBy + ? `Created by ${listStandardResults[0].appliedBy}` + : 'None' + } + title={`${enabledWarningsCount} out of ${totalAvailableStandards}`} + value="Enabled Warnings" + /> + + + 0 + ? Math.round((enabledAlertsCount / totalAvailableStandards) * 1000) / 10 + : 0, + }} + text={ + listStandardResults.length > 0 && listStandardResults[0].appliedBy + ? `Created by ${listStandardResults[0].appliedBy}` + : 'None' + } + title={`${enabledAlertsCount} out of ${totalAvailableStandards}`} + value="Enabled Alerts" + /> + + + 0 + ? Math.round((enabledRemediationsCount / totalAvailableStandards) * 1000) / + 10 + : 0, + }} + text={ + listStandardResults.length > 0 && listStandardResults[0].appliedBy + ? `Created by ${listStandardResults[0].appliedBy}` + : 'None' + } + title={`${enabledRemediationsCount} out of ${totalAvailableStandards}`} + value="Enabled Remediations" + /> + + @@ -400,69 +460,6 @@ const ApplyNewStandard = () => { return ( - - 0 - ? Math.round( - (enabledWarningsCount / totalAvailableStandards) * 1000, - ) / 10 - : 0, - }} - text={ - listStandardResults[0].appliedBy - ? `Created by ${listStandardResults[0].appliedBy}` - : 'None' - } - title={`${enabledWarningsCount} out of ${totalAvailableStandards}`} - value="Enabled Warnings" - /> - - - 0 - ? Math.round( - (enabledAlertsCount / totalAvailableStandards) * 1000, - ) / 10 - : 0, - }} - text={ - listStandardResults[0].appliedBy - ? `Created by ${listStandardResults[0].appliedBy}` - : 'None' - } - title={`${enabledAlertsCount} out of ${totalAvailableStandards}`} - value="Enabled Alerts" - /> - - - 0 - ? Math.round( - (enabledRemediationsCount / totalAvailableStandards) * 1000, - ) / 10 - : 0, - }} - text={ - listStandardResults[0].appliedBy - ? `Created by ${listStandardResults[0].appliedBy}` - : 'None' - } - title={`${enabledRemediationsCount} out of ${totalAvailableStandards}`} - value="Enabled Remediations" - /> - Date: Fri, 10 May 2024 13:29:41 +0200 Subject: [PATCH 52/92] fixed error with lookup --- src/views/tenant/administration/TenantLookup.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/views/tenant/administration/TenantLookup.jsx b/src/views/tenant/administration/TenantLookup.jsx index abb95f701571..f94d73ed5fb0 100644 --- a/src/views/tenant/administration/TenantLookup.jsx +++ b/src/views/tenant/administration/TenantLookup.jsx @@ -122,25 +122,25 @@ const GraphExplorer = () => {

    Tenant Name

    {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.displayName} + {graphrequest.data?.GraphRequest?.displayName}

    Tenant ID

    {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.tenantId} + {graphrequest.data?.GraphRequest?.tenantId}

    Default Domain Name

    {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.defaultDomainName} + {graphrequest.data?.GraphRequest?.defaultDomainName}

    Tenant Brand Name

    {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest.federationBrandName} - {graphrequest.data?.GraphRequest.federationBrandName === null && + {graphrequest.data?.GraphRequest?.federationBrandName} + {graphrequest.data?.GraphRequest?.federationBrandName === null && 'No brand name set'}
    From 492535d268acb96aa6876fc3eca0fdae0c9eaaf1 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Fri, 10 May 2024 13:31:35 +0200 Subject: [PATCH 53/92] prettification --- src/views/tenant/administration/TenantLookup.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/views/tenant/administration/TenantLookup.jsx b/src/views/tenant/administration/TenantLookup.jsx index f94d73ed5fb0..ced62911ae8d 100644 --- a/src/views/tenant/administration/TenantLookup.jsx +++ b/src/views/tenant/administration/TenantLookup.jsx @@ -122,7 +122,9 @@ const GraphExplorer = () => {

    Tenant Name

    {graphrequest.isFetching && } - {graphrequest.data?.GraphRequest?.displayName} + {graphrequest.data?.GraphRequest?.displayName + ? graphrequest.data?.GraphRequest?.displayName + : 'Could not find tenant - Is this a M365 domain name?'}

    Tenant ID

    From 7a5a54485b3ea87a6ce8dfdadad157d55804b486 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 10 May 2024 12:46:08 -0400 Subject: [PATCH 54/92] Update edit standards page - Fix counts to include consolidated - Conditionally hide all tenant label if overrode - Conditionally disable action buttons if appllied at all tenant level --- .../tenant/standards/ListAppliedStandards.jsx | 105 +++++++++++++++--- 1 file changed, 87 insertions(+), 18 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index 81c20f247c79..cdb3960b0f86 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -74,6 +74,9 @@ const ApplyNewStandard = () => { const [templateStandard, setTemplateStandard] = useState() const [loadedTemplate, setLoadedTemplate] = useState(false) const [loadingTemplate, setLoadingTemplate] = useState(false) + const [enabledAlertsCount, setEnabledAlertsCount] = useState(0) + const [enabledRemediationsCount, setEnabledRemediationsCount] = useState(0) + const [enabledWarningsCount, setEnabledWarningsCount] = useState(0) const { data: listStandardTemplates = [], refetch: refetchStandardsTemplates } = useGenericGetRequestQuery({ @@ -265,6 +268,11 @@ const ApplyNewStandard = () => { const { data: listStandardsAllTenants = [] } = useGenericGetRequestQuery({ path: 'api/listStandards', }) + const { data: consolidatedStandards = [], isSuccess: consolidatedSuccess } = + useGenericGetRequestQuery({ + path: 'api/listStandards', + params: { TenantFilter: tenantDomain, ShowConsolidated: true }, + }) const { data: listStandardResults = [], @@ -305,11 +313,30 @@ const ApplyNewStandard = () => { } const keys = item.name.split('.') let value = keys.reduce((prev, curr) => prev && prev[curr], allTenantsStandard) - if (!value || !value[type]) { + if ( + !value || + !value[type] || + listStandardResults[0]?.standards?.OverrideAllTenants?.remediate === true + ) { return '' } return `* Enabled via All Tenants` } + function isAllTenantEnabled(item, type) { + if (!item || !item.name) { + return '' + } + const keys = item.name.split('.') + let value = keys.reduce((prev, curr) => prev && prev[curr], allTenantsStandard) + if ( + !value || + !value[type] || + listStandardResults[0]?.standards?.OverrideAllTenants?.remediate === true + ) { + return false + } + return true + } const groupedStandards = allStandardsList.reduce((acc, obj) => { acc[obj.cat] = acc[obj.cat] || [] @@ -320,26 +347,59 @@ const ApplyNewStandard = () => { // Function to count enabled standards function countEnabledStandards(standards, type) { let count = 0 - Object.keys(standards).forEach((key) => { - const standard = standards[key] - // Check if 'Enabled' exists and the specific type is true, for non-v2 standards - if (standard?.Enabled && standard?.Enabled[type]) { - count++ - } else if (standard && standard[type]) { - // Check if the type exists directly under the standard - count++ - } - }) + if (standards.length > 0) { + Object.keys(standards).forEach((standard) => { + var setting = standard?.Settings + if (setting) { + if (type in Object.keys(setting) && setting[type] === true) { + count++ + } + } + }) + } return count } // Assuming listStandardResults[0] contains your JSON object - const enabledStandards = listStandardResults[0] ? listStandardResults[0].standards : {} - const enabledAlertsCount = countEnabledStandards(enabledStandards, 'alert') + //console.log(consolidatedStandards) + const enabledStandards = consolidatedStandards ? consolidatedStandards : [] + /*const enabledAlertsCount = countEnabledStandards(enabledStandards, 'alert') const enabledRemediationsCount = countEnabledStandards(enabledStandards, 'remediate') - const enabledWarningsCount = countEnabledStandards(enabledStandards, 'report') + const enabledWarningsCount = countEnabledStandards(enabledStandards, 'report') */ const totalAvailableStandards = allStandardsList.length + useEffect(() => { + if (consolidatedSuccess && consolidatedStandards.length > 0) { + var actions = ['alert', 'remediate', 'report'] + var enabledCounts = { + alert: 0, + remediate: 0, + report: 0, + } + consolidatedStandards.map((standard) => { + console.log(standard.Standard) + if (standard?.Settings) { + actions.map((action) => { + if (standard?.Settings[action] === true) { + enabledCounts[action]++ + } + }) + } + }) + console.log(enabledCounts) + + setEnabledAlertsCount(enabledCounts['alert']) + setEnabledRemediationsCount(enabledCounts['remediate']) + setEnabledWarningsCount(enabledCounts['report']) + } + }, [ + consolidatedStandards, + consolidatedSuccess, + setEnabledAlertsCount, + setEnabledRemediationsCount, + setEnabledWarningsCount, + ]) + return ( <> @@ -385,7 +445,7 @@ const ApplyNewStandard = () => { : 'None' } title={`${enabledWarningsCount} out of ${totalAvailableStandards}`} - value="Enabled Warnings" + value="Enabled Reports" />
    @@ -558,7 +618,10 @@ const ApplyNewStandard = () => {
    Report
    @@ -567,7 +630,10 @@ const ApplyNewStandard = () => {
    Alert
    @@ -576,7 +642,10 @@ const ApplyNewStandard = () => {
    Remediate
    From 526b26258cd0a56239b647ac82bdb45efa99b405 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 10 May 2024 12:51:37 -0400 Subject: [PATCH 55/92] Revert "Merge branch 'jit-admin' into dev" This reverts commit 41e17d3568d2a341970fff88a5aa2bc329ad94fc, reversing changes made to 1fc0b8bb646b1a893b8f676fb3fc3b6d7dacd493. --- src/_nav.jsx | 5 - src/importsMap.jsx | 1 - src/routes.json | 6 - .../administration/DeployJITAdmin.jsx | 213 ------------------ 4 files changed, 225 deletions(-) delete mode 100644 src/views/identity/administration/DeployJITAdmin.jsx diff --git a/src/_nav.jsx b/src/_nav.jsx index 1454e5afed55..b0ec445ccd13 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -75,11 +75,6 @@ const _nav = [ name: 'Roles', to: '/identity/administration/roles', }, - { - component: CNavItem, - name: 'JIT Admin', - to: '/identity/administration/users/jit-admin', - }, { component: CNavItem, name: 'Offboarding Wizard', diff --git a/src/importsMap.jsx b/src/importsMap.jsx index 8563f94c50a0..7b7589049b42 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -12,7 +12,6 @@ import React from 'react' "/identity/administration/users/edit": React.lazy(() => import('./views/identity/administration/EditUser')), "/identity/administration/users/view": React.lazy(() => import('./views/identity/administration/ViewUser')), "/identity/administration/users/InviteGuest": React.lazy(() => import('./views/identity/administration/InviteGuest')), - "/identity/administration/users/jit-admin": React.lazy(() => import('./views/identity/administration/DeployJITAdmin')), "/identity/administration/ViewBec": React.lazy(() => import('./views/identity/administration/ViewBEC')), "/identity/administration/users": React.lazy(() => import('./views/identity/administration/Users')), "/identity/administration/devices": React.lazy(() => import('./views/identity/administration/Devices')), diff --git a/src/routes.json b/src/routes.json index 224f140c1bd7..e1d382459781 100644 --- a/src/routes.json +++ b/src/routes.json @@ -76,12 +76,6 @@ "component": "views/identity/administration/InviteGuest", "allowedRoles": ["admin", "editor", "readonly"] }, - { - "path": "/identity/administration/users/jit-admin", - "name": "JIT Admin", - "component": "views/identity/administration/DeployJITAdmin", - "allowedRoles": ["admin", "editor", "readonly"] - }, { "path": "/identity/administration/ViewBec", "name": "View BEC", diff --git a/src/views/identity/administration/DeployJITAdmin.jsx b/src/views/identity/administration/DeployJITAdmin.jsx deleted file mode 100644 index dfbdf4090964..000000000000 --- a/src/views/identity/administration/DeployJITAdmin.jsx +++ /dev/null @@ -1,213 +0,0 @@ -import React, { useState } from 'react' -import { CButton, CCallout, CCol, CForm, CRow, CSpinner, CTooltip } from '@coreui/react' -import { useSelector } from 'react-redux' -import { Field, Form, FormSpy } from 'react-final-form' -import { Condition, RFFCFormRadio, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms' -import { - useGenericGetRequestQuery, - useLazyGenericGetRequestQuery, - useLazyGenericPostRequestQuery, -} from 'src/store/api/app' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons' -import { CippContentCard, CippPage, CippPageList } from 'src/components/layout' -import { CellTip } from 'src/components/tables/CellGenericFormat' -import 'react-datepicker/dist/react-datepicker.css' -import { CippActionsOffcanvas, ModalService, TenantSelector } from 'src/components/utilities' -import arrayMutators from 'final-form-arrays' -import DatePicker from 'react-datepicker' -import 'react-datepicker/dist/react-datepicker.css' -import { useListUsersQuery } from 'src/store/api/users' -import { useListConditionalAccessPoliciesQuery } from 'src/store/api/tenants' -import GDAPRoles from 'src/data/GDAPRoles' - -const DeployJITAdmin = () => { - const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery() - const currentDate = new Date() - const [startDate, setStartDate] = useState(currentDate) - const [endDate, setEndDate] = useState(currentDate) - - const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) - const [refreshState, setRefreshState] = useState(false) - const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() - - const onSubmit = (values) => { - const startTime = Math.floor(startDate.getTime() / 1000) - const endTime = Math.floor(endDate.getTime() / 1000) - const shippedValues = { - tenantFilter: tenantDomain, - UserId: values.UserId?.value, - PolicyId: values.PolicyId?.value, - StartDate: startTime, - EndDate: endTime, - ExpireAction: values?.expireAction ?? 'delete', - } - genericPostRequest({ path: '/api/ExecJITAdmin', values: shippedValues }).then((res) => { - setRefreshState(res.requestId) - }) - } - - const { - data: users = [], - isFetching: usersIsFetching, - error: usersError, - } = useListUsersQuery({ tenantDomain }) - - return ( - - <> - - - - { - return ( - -

    - JIT Admin creates an account that is usable for a specific period of time. - Enter a username, select admin roles, date range and expiration action. -

    - - - - {(props) => } - - - -
    -
    - - - - - - - - - - ({ - value: user.id, - name: `${user.displayName} <${user.userPrincipalName}>`, - }))} - placeholder={!usersIsFetching ? 'Select user' : 'Loading...'} - name="UserId" - isLoading={usersIsFetching} - /> - - - - - ({ - value: role.ObjectId, - name: role.Name, - }))} - multi={true} - placeholder="Select Roles" - name="AdminRoles" - /> - - - - - - setStartDate(date)} - /> - - - - setEndDate(date)} - /> - - - - - - - - - - - Add JIT Admin - {postResults.isFetching && ( - - )} - - - - {postResults.isSuccess && ( - -
  • {postResults.data.Results}
  • -
    - )} - {getResults.isFetching && ( - - Loading - - )} - {getResults.isSuccess && ( - {getResults.data?.Results} - )} - {getResults.isError && ( - - Could not connect to API: {getResults.error.message} - - )} -
    - ) - }} - /> -
    -
    -
    - -
    - ) -} - -export default DeployJITAdmin From 3d57a56105a050d4353a62785eb0539f87ddb07d Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 10 May 2024 13:37:37 -0400 Subject: [PATCH 56/92] Standards - Fix all tenant settings Add FormSpy on enabled settings Remove disable on all tenants --- .../tenant/standards/ListAppliedStandards.jsx | 335 +++++++++--------- 1 file changed, 170 insertions(+), 165 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index cdb3960b0f86..66966301559f 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -307,21 +307,6 @@ const ApplyNewStandard = () => { (tenant) => tenant.displayName === 'AllTenants', ) - function getLabel(item, type) { - if (!item || !item.name) { - return '' - } - const keys = item.name.split('.') - let value = keys.reduce((prev, curr) => prev && prev[curr], allTenantsStandard) - if ( - !value || - !value[type] || - listStandardResults[0]?.standards?.OverrideAllTenants?.remediate === true - ) { - return '' - } - return `* Enabled via All Tenants` - } function isAllTenantEnabled(item, type) { if (!item || !item.name) { return '' @@ -344,28 +329,6 @@ const ApplyNewStandard = () => { return acc }, {}) - // Function to count enabled standards - function countEnabledStandards(standards, type) { - let count = 0 - if (standards.length > 0) { - Object.keys(standards).forEach((standard) => { - var setting = standard?.Settings - if (setting) { - if (type in Object.keys(setting) && setting[type] === true) { - count++ - } - } - }) - } - return count - } - - // Assuming listStandardResults[0] contains your JSON object - //console.log(consolidatedStandards) - const enabledStandards = consolidatedStandards ? consolidatedStandards : [] - /*const enabledAlertsCount = countEnabledStandards(enabledStandards, 'alert') - const enabledRemediationsCount = countEnabledStandards(enabledStandards, 'remediate') - const enabledWarningsCount = countEnabledStandards(enabledStandards, 'report') */ const totalAvailableStandards = allStandardsList.length useEffect(() => { @@ -386,8 +349,6 @@ const ApplyNewStandard = () => { }) } }) - console.log(enabledCounts) - setEnabledAlertsCount(enabledCounts['alert']) setEnabledRemediationsCount(enabledCounts['remediate']) setEnabledWarningsCount(enabledCounts['report']) @@ -588,137 +549,181 @@ const ApplyNewStandard = () => { )} - {Object.keys(groupedStandards).map((cat, catIndex) => ( - - {cat} - - {groupedStandards[cat].map((obj, index) => ( - - -
    -
    {obj.label}
    -
    - {obj.impact} -
    -
    -

    - {obj.helpText} -

    -
    - -
    Report
    - -
    - -
    Alert
    - -
    - -
    Remediate
    - -
    - -
    Optional Input
    - {obj.addedComponent && - obj.addedComponent.map((component) => ( - <> - {component.type === 'Select' && ( - - )} - {component.type === 'input' && ( - - )} - {component.type === 'number' && ( - - )} - {component.type === 'boolean' && ( + + {/* eslint-disable react/prop-types */} + {(props) => { + return ( + <> + {Object.keys(groupedStandards).map((cat, catIndex) => ( + + {cat} + + {groupedStandards[cat].map((obj, index) => ( + + +
    +
    {obj.label}
    +
    + + {obj.impact} + +
    +
    +

    + {obj.helpText} +

    +
    + +
    Report
    - )} - {component.type === 'AdminRolesMultiSelect' && ( - ({ - value: role.ObjectId, - name: role.Name, - }))} +
    + +
    Alert
    + - )} - {component.type === 'TimezoneSelect' && ( - ({ - value: tz.timezone, - name: tz.timezone, - }))} +
    + +
    Remediate
    + - )} - +
    + +
    Optional Input
    + {obj.addedComponent && + obj.addedComponent.map((component) => ( + <> + {component.type === 'Select' && ( + + )} + {component.type === 'input' && ( + + )} + {component.type === 'number' && ( + + )} + {component.type === 'boolean' && ( + + )} + {component.type === + 'AdminRolesMultiSelect' && ( + ({ + value: role.ObjectId, + name: role.Name, + }))} + /> + )} + {component.type === 'TimezoneSelect' && ( + ({ + value: tz.timezone, + name: tz.timezone, + }))} + /> + )} + + ))} +
    +
    ))} -
    -
    - ))} -
    -
    - ))} + + + ))} + + ) + }} + Templates Standard Deployment From 50f2645e4762006c1319aaf770a0525f47949d2c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 10 May 2024 14:10:54 -0400 Subject: [PATCH 57/92] Update ListAppliedStandards.jsx --- src/views/tenant/standards/ListAppliedStandards.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index 66966301559f..3a726c392f1b 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -262,7 +262,7 @@ const ApplyNewStandard = () => { }) const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) - console.log('tenantDomain', tenantDomain) + //console.log('tenantDomain', tenantDomain) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() const { data: listStandardsAllTenants = [] } = useGenericGetRequestQuery({ @@ -340,7 +340,7 @@ const ApplyNewStandard = () => { report: 0, } consolidatedStandards.map((standard) => { - console.log(standard.Standard) + //console.log(standard.Standard) if (standard?.Settings) { actions.map((action) => { if (standard?.Settings[action] === true) { @@ -634,7 +634,7 @@ const ApplyNewStandard = () => { obj.disabledFeatures?.remediate || (isAllTenantEnabled(obj, 'remediate') && tenantDomain !== 'AllTenants' && - props.standards?.OverrideAllTenants + props.values.standards?.OverrideAllTenants ?.remediate !== true) } helpText={ @@ -643,7 +643,7 @@ const ApplyNewStandard = () => { sublabel={ isAllTenantEnabled(obj, 'remediate') && tenantDomain !== 'AllTenants' && - props.standards?.OverrideAllTenants + props.values.standards?.OverrideAllTenants ?.remediate !== true ? '* Enabled via All Tenants' : '' From fc037913efebb48a4269fb8a7c618ce96c93c4c5 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 10 May 2024 14:11:28 -0400 Subject: [PATCH 58/92] Update DefaultLayout.jsx --- src/layout/DefaultLayout.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/DefaultLayout.jsx b/src/layout/DefaultLayout.jsx index 0b08e4ad8b8c..23bbc527b527 100644 --- a/src/layout/DefaultLayout.jsx +++ b/src/layout/DefaultLayout.jsx @@ -23,7 +23,7 @@ const DefaultLayout = () => { useEffect(() => { let route = routes.find((route) => route.path.toLowerCase() === location.pathname.toLowerCase()) if (route?.name) { - console.log(route) + //console.log(route) setTitle(route.name) } }, [setTitle, location.pathname]) From fb402d189196b3fb5f0f4c896355f766a4e9ded3 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 10 May 2024 16:31:12 -0400 Subject: [PATCH 59/92] fix standards layout add refetch for consolidated --- .../tenant/standards/ListAppliedStandards.jsx | 1333 ++++++++--------- 1 file changed, 665 insertions(+), 668 deletions(-) diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx index 3a726c392f1b..484ec3862a36 100644 --- a/src/views/tenant/standards/ListAppliedStandards.jsx +++ b/src/views/tenant/standards/ListAppliedStandards.jsx @@ -268,11 +268,14 @@ const ApplyNewStandard = () => { const { data: listStandardsAllTenants = [] } = useGenericGetRequestQuery({ path: 'api/listStandards', }) - const { data: consolidatedStandards = [], isSuccess: consolidatedSuccess } = - useGenericGetRequestQuery({ - path: 'api/listStandards', - params: { TenantFilter: tenantDomain, ShowConsolidated: true }, - }) + const { + data: consolidatedStandards = [], + isSuccess: consolidatedSuccess, + refetch: refetchConsolidated, + } = useGenericGetRequestQuery({ + path: 'api/listStandards', + params: { TenantFilter: tenantDomain, ShowConsolidated: true }, + }) const { data: listStandardResults = [], @@ -296,7 +299,10 @@ const ApplyNewStandard = () => { genericPostRequest({ path: '/api/AddStandardsDeploy', values: { ...values.standards, tenant: tenantDomain }, - }).then(() => refetchStandards()) + }).then(() => { + refetchStandards() + refetchConsolidated() + }) } const [intuneGetRequest, intuneTemplates] = useLazyGenericGetRequestQuery() const [transportGetRequest, transportTemplates] = useLazyGenericGetRequestQuery() @@ -389,685 +395,676 @@ const ApplyNewStandard = () => { {getResults.error.message} )} - - - 0 - ? Math.round((enabledWarningsCount / totalAvailableStandards) * 1000) / 10 - : 0, - }} - text={ - listStandardResults.length > 0 && listStandardResults[0].appliedBy - ? `Created by ${listStandardResults[0].appliedBy}` - : 'None' - } - title={`${enabledWarningsCount} out of ${totalAvailableStandards}`} - value="Enabled Reports" - /> - - - 0 - ? Math.round((enabledAlertsCount / totalAvailableStandards) * 1000) / 10 - : 0, - }} - text={ - listStandardResults.length > 0 && listStandardResults[0].appliedBy - ? `Created by ${listStandardResults[0].appliedBy}` - : 'None' - } - title={`${enabledAlertsCount} out of ${totalAvailableStandards}`} - value="Enabled Alerts" - /> - - - 0 - ? Math.round((enabledRemediationsCount / totalAvailableStandards) * 1000) / - 10 - : 0, - }} - text={ - listStandardResults.length > 0 && listStandardResults[0].appliedBy - ? `Created by ${listStandardResults[0].appliedBy}` - : 'None' - } - title={`${enabledRemediationsCount} out of ${totalAvailableStandards}`} - value="Enabled Remediations" - /> - - - - - +
    +
    + + + 0 + ? Math.round((enabledWarningsCount / totalAvailableStandards) * 1000) / 10 + : 0, + }} + text={ + listStandardResults.length > 0 && listStandardResults[0].appliedBy + ? `Created by ${listStandardResults[0].appliedBy}` + : 'None' } - title={`List and edit standard - ${tenantDomain}`} - > - {isFetching && } - {intuneTemplates.isUninitialized && - intuneGetRequest({ path: 'api/ListIntuneTemplates' })} - {transportTemplates.isUninitialized && - transportGetRequest({ path: 'api/ListTransportRulesTemplates' })} - {caTemplates.isUninitialized && caGetRequest({ path: 'api/ListCAtemplates' })} - {exConnectorTemplates.isUninitialized && - exConnectorGetRequest({ path: 'api/ListExConnectorTemplates' })} - {groupTemplates.isUninitialized && - groupGetRequest({ path: 'api/ListGroupTemplates' })} - {isSuccess && !isFetching && ( - { - return ( - - - - {tenantDomain !== 'AllTenants' && ( - - General Standard Settings - - - -
    -
    Do not apply All Tenants Standard to this tenant
    -
    - Minimal Impact -
    -
    -

    - - Enabling this feature excludes this tenant from any - top-level "All Tenants" standard. This means that only the - standards you explicitly set for this tenant will be - applied. Standards previously applied by the "All Tenants" - standard will not be reverted. - -

    -
    - -
    Report
    - -
    - -
    Alert
    - -
    - -
    Remediate
    - -
    - -
    Optional Input
    -
    -
    -
    -
    - )} - - {/* eslint-disable react/prop-types */} - {(props) => { - return ( - <> - {Object.keys(groupedStandards).map((cat, catIndex) => ( - - {cat} - - {groupedStandards[cat].map((obj, index) => ( - - -
    -
    {obj.label}
    -
    - - {obj.impact} - -
    -
    -

    - {obj.helpText} -

    -
    - -
    Report
    - -
    - -
    Alert
    - -
    - -
    Remediate
    - -
    - -
    Optional Input
    - {obj.addedComponent && - obj.addedComponent.map((component) => ( - <> - {component.type === 'Select' && ( - - )} - {component.type === 'input' && ( - - )} - {component.type === 'number' && ( - - )} - {component.type === 'boolean' && ( - - )} - {component.type === - 'AdminRolesMultiSelect' && ( - ({ - value: role.ObjectId, - name: role.Name, - }))} - /> - )} - {component.type === 'TimezoneSelect' && ( - ({ - value: tz.timezone, - name: tz.timezone, - }))} - /> - )} - - ))} -
    -
    - ))} -
    -
    - ))} - - ) - }} -
    - - Templates Standard Deployment - - {[ - { - name: 'Intune Template', - switchName: 'standards.IntuneTemplate', - assignable: true, - templates: intuneTemplates, - }, - { - name: 'Transport Rule Template', - switchName: 'standards.TransportRuleTemplate', - templates: transportTemplates, - }, - { - name: 'Conditional Access Template', - switchName: 'standards.ConditionalAccess', - templates: caTemplates, - }, - { - name: 'Exchange Connector Template', - switchName: 'standards.ExConnector', - templates: exConnectorTemplates, - }, - { - name: 'Group Template', - switchName: 'standards.GroupTemplate', - templates: groupTemplates, - }, - ].map((template, index) => ( - - -
    {template.name}
    - Deploy {template.name} -
    - -
    Report
    - -
    - -
    Alert
    - -
    - -
    Remediate
    - -
    - -
    Optional Input
    - {template.templates.isSuccess && ( - ({ - value: t.GUID, - name: t.name || t.Displayname || t.displayName, - }))} - placeholder="Select a template" - label={`Choose your ${template.name}`} - /> - )} - {template.assignable && ( - <> - - - - - - - +
    + + 0 + ? Math.round((enabledAlertsCount / totalAvailableStandards) * 1000) / 10 + : 0, + }} + text={ + listStandardResults.length > 0 && listStandardResults[0].appliedBy + ? `Created by ${listStandardResults[0].appliedBy}` + : 'None' + } + title={`${enabledAlertsCount} out of ${totalAvailableStandards}`} + value="Enabled Alerts" + /> + + + 0 + ? Math.round((enabledRemediationsCount / totalAvailableStandards) * 1000) / 10 + : 0, + }} + text={ + listStandardResults.length > 0 && listStandardResults[0].appliedBy + ? `Created by ${listStandardResults[0].appliedBy}` + : 'None' + } + title={`${enabledRemediationsCount} out of ${totalAvailableStandards}`} + value="Enabled Remediations" + /> + +
    + + + + } + title={`List and edit standard - ${tenantDomain}`} + className="mb-3" + > + {isFetching && } + {intuneTemplates.isUninitialized && intuneGetRequest({ path: 'api/ListIntuneTemplates' })} + {transportTemplates.isUninitialized && + transportGetRequest({ path: 'api/ListTransportRulesTemplates' })} + {caTemplates.isUninitialized && caGetRequest({ path: 'api/ListCAtemplates' })} + {exConnectorTemplates.isUninitialized && + exConnectorGetRequest({ path: 'api/ListExConnectorTemplates' })} + {groupTemplates.isUninitialized && groupGetRequest({ path: 'api/ListGroupTemplates' })} + {isSuccess && !isFetching && ( + { + return ( + + + + {tenantDomain !== 'AllTenants' && ( + + General Standard Settings + + + +
    +
    Do not apply All Tenants Standard to this tenant
    +
    + Minimal Impact +
    +
    +

    + + Enabling this feature excludes this tenant from any top-level + "All Tenants" standard. This means that only the standards you + explicitly set for this tenant will be applied. Standards + previously applied by the "All Tenants" standard will not be + reverted. + +

    +
    + +
    Report
    + +
    + +
    Alert
    + +
    + +
    Remediate
    + +
    + +
    Optional Input
    +
    +
    +
    +
    + )} + + {/* eslint-disable react/prop-types */} + {(props) => { + return ( + <> + {Object.keys(groupedStandards).map((cat, catIndex) => ( + + {cat} + + {groupedStandards[cat].map((obj, index) => ( + + +
    +
    {obj.label}
    +
    + + {obj.impact} + +
    +
    +

    + {obj.helpText} +

    +
    + +
    Report
    + +
    + +
    Alert
    + - - - )} -
    -
    +
    + +
    Remediate
    + +
    + +
    Optional Input
    + {obj.addedComponent && + obj.addedComponent.map((component) => ( + <> + {component.type === 'Select' && ( + + )} + {component.type === 'input' && ( + + )} + {component.type === 'number' && ( + + )} + {component.type === 'boolean' && ( + + )} + {component.type === 'AdminRolesMultiSelect' && ( + ({ + value: role.ObjectId, + name: role.Name, + }))} + /> + )} + {component.type === 'TimezoneSelect' && ( + ({ + value: tz.timezone, + name: tz.timezone, + }))} + /> + )} + + ))} +
    +
    + ))} + + ))} - - -
    Autopilot Profile
    - Deploy Autopilot profile -
    - -
    Report
    - -
    - -
    Alert
    - -
    - -
    Remediate
    - -
    - -
    Optional Input
    - - - - - - - - - - - - + + ) + }} + + + Templates Standard Deployment + + {[ + { + name: 'Intune Template', + switchName: 'standards.IntuneTemplate', + assignable: true, + templates: intuneTemplates, + }, + { + name: 'Transport Rule Template', + switchName: 'standards.TransportRuleTemplate', + templates: transportTemplates, + }, + { + name: 'Conditional Access Template', + switchName: 'standards.ConditionalAccess', + templates: caTemplates, + }, + { + name: 'Exchange Connector Template', + switchName: 'standards.ExConnector', + templates: exConnectorTemplates, + }, + { + name: 'Group Template', + switchName: 'standards.GroupTemplate', + templates: groupTemplates, + }, + ].map((template, index) => ( + + +
    {template.name}
    + Deploy {template.name} +
    + +
    Report
    + +
    + +
    Alert
    + +
    + +
    Remediate
    + +
    + +
    Optional Input
    + {template.templates.isSuccess && ( + ({ + value: t.GUID, + name: t.name || t.Displayname || t.displayName, + }))} + placeholder="Select a template" + label={`Choose your ${template.name}`} + /> + )} + {template.assignable && ( + <> + + + + + + -

    -
    -
    - - - - - - - - - + + )} +
    +
    + ))} + + +
    Autopilot Profile
    + Deploy Autopilot profile +
    + +
    Report
    + +
    + +
    Alert
    + +
    + +
    Remediate
    + +
    + +
    Optional Input
    + + + - - -
    Autopilot Status Page
    - Deploy Autopilot Status Page -
    - -
    Report
    - + + + - -
    Alert
    - +
    + + + +

    +
    + + + + + + + + + +
    +
    + + +
    Autopilot Status Page
    + Deploy Autopilot Status Page +
    + +
    Report
    + +
    + +
    Alert
    + +
    + +
    Remediate
    + +
    + +
    Optional Input
    + -
    Remediate
    - -
    - -
    Optional Input
    - - - - - - - - - - - - - - - - - +
    + + + - - - -
    + + + + + + + +
    +
    + + + +
    - - {postResults.isSuccess && ( - {postResults.data.Results} - )} - - - - Save - {postResults.isFetching && ( - - )} - - - - {listStandardResults[0].appliedBy && ( - - )} - - {/* eslint-disable react/prop-types */} - {(props) => { - return ( - <> - templateSave(props.values)} - disabled={submitting} - > - {execSaveResults.isFetching && ( - - )} - {execSaveResults.error && ( - - )} - {execSaveResults.isSuccess && ( - - )} - Save as template - - - ) - }} - - - - -
    - ) - }} - /> - )} -
    - - + + {postResults.isSuccess && ( + {postResults.data.Results} + )} + + + + Save + {postResults.isFetching && ( + + )} + + + + {listStandardResults[0].appliedBy && } + + {/* eslint-disable react/prop-types */} + {(props) => { + return ( + <> + templateSave(props.values)} + disabled={submitting} + > + {execSaveResults.isFetching && ( + + )} + {execSaveResults.error && ( + + )} + {execSaveResults.isSuccess && ( + + )} + Save as template + + + ) + }} + + + + + + ) + }} + /> + )} + ) From 7f1068b73fb523d47afae9eab7cb4c12623af5b8 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 11 May 2024 14:48:07 +0200 Subject: [PATCH 60/92] auto select recommended time. --- .../tenant/administration/AlertWizard.jsx | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index cdebe32a51c7..8baa96022d6f 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -41,6 +41,8 @@ const AlertWizard = () => { const [queryError, setQueryError] = useState(false) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() const [alertType, setAlertType] = useState(false) + const [recommendedRecurrence, setRecommendedRecurrence] = useState() + const [currentFormState, setCurrentFormState] = useState() const { data: tenant = {}, isFetching, @@ -74,6 +76,8 @@ const AlertWizard = () => { const initialValues = { ...tenant[0], + ...currentFormState?.values, + ...recommendedRecurrence, } const recurrenceOptions = [ @@ -164,6 +168,26 @@ const AlertWizard = () => { } const [addedEvent, setAddedEvent] = React.useState(1) + const getRecurrenceOptions = () => { + const values = currentFormState?.values + if (values) { + //console.log(currentFormState) + const updatedRecurrenceOptions = recurrenceOptions.map((opt) => ({ + ...opt, + name: opt.name.replace(' (Recommended)', ''), + })) + const recommendedValue = values.command?.value?.recommendedRunInterval + const option = updatedRecurrenceOptions.find((opt) => opt.value === recommendedValue) + if (option) { + option.name += ' (Recommended)' + if (option.value !== recommendedRecurrence?.Recurrence.value) { + setRecommendedRecurrence({ Recurrence: { value: option.value, label: option.name } }) + } + } + return updatedRecurrenceOptions + } + } + return ( {!queryError && ( @@ -404,32 +428,15 @@ const AlertWizard = () => { - - {(props) => { - const updatedRecurrenceOptions = recurrenceOptions.map( - (opt) => ({ - ...opt, - name: opt.name.replace(' (Recommended)', ''), - }), - ) - const recommendedValue = - props.values.command?.value?.recommendedRunInterval - const option = updatedRecurrenceOptions.find( - (opt) => opt.value === recommendedValue, - ) - if (option) { - option.name += ' (Recommended)' - } - return ( - - ) - }} - + setCurrentFormState(formvalues)} + /> + From 42e9b32cfb06f1ce992ad3ac6094dcfd2247d71c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 11 May 2024 19:05:16 +0200 Subject: [PATCH 61/92] prepping templates --- src/data/AuditLogSchema.json | 81 +++++++++++++++- src/data/AuditLogTemplates.json | 96 +++++++++++++++++++ .../tenant/administration/AlertWizard.jsx | 83 +++------------- 3 files changed, 189 insertions(+), 71 deletions(-) create mode 100644 src/data/AuditLogTemplates.json diff --git a/src/data/AuditLogSchema.json b/src/data/AuditLogSchema.json index 7e0054b18aa3..5ad677a63f51 100644 --- a/src/data/AuditLogSchema.json +++ b/src/data/AuditLogSchema.json @@ -3,7 +3,7 @@ "Id": "String", "RecordType": "List:AuditLogRecordType", "CreationTime": "String", - "Operation": "String", + "Operation": "List:Operation", "OrganizationId": "String", "UserType": "List:UserType", "UserKey": "String", @@ -22,7 +22,7 @@ "Id": "Combination GUID", "RecordType": "List:AuditLogRecordType", "CreationTime": "String", - "Operation": "String", + "Operation": "List:Operation", "OrganizationId": "Guid", "UserType": "List:UserType", "UserKey": "String", @@ -68,6 +68,83 @@ "Errorvalue": "String", "LogonError": "String" }, + "List:Operation": [ + { "value": "accessed mailbox items", "name": "accessed mailbox items" }, + { "value": "add delegation entry.", "name": "added delegation entry" }, + { "value": "add domain to company.", "name": "added domain to company" }, + { "value": "add group.", "name": "added group" }, + { "value": "add member to group.", "name": "added member to group" }, + { "value": "add mailboxpermission", "name": "added delegate mailbox permissions" }, + { "value": "add member to role.", "name": "added member to role" }, + { "value": "add partner to company.", "name": "added a partner to the directory" }, + { "value": "add service principal.", "name": "added service principal" }, + { + "value": "add service principal credentials.", + "name": "added credentials to a service principal" + }, + { "value": "add user.", "name": "added user" }, + { "value": "addfolderpermissions", "name": "added permissions to folder" }, + { "value": "applyrecordlabel", "name": "labeled message as a record" }, + { "value": "change user license.", "name": "changed user license" }, + { "value": "change user password.", "name": "changed user password" }, + { "value": "copy", "name": "copied messages to another folder" }, + { "value": "create", "name": "created mailbox item" }, + { "value": "delete group.", "name": "deleted group" }, + { "value": "delete user.", "name": "deleted user" }, + { "value": "harddelete", "name": "purged messages from the mailbox" }, + { "value": "mailboxlogin", "name": "user signed in to mailbox" }, + { "value": "move", "name": "moved messages to another folder" }, + { "value": "movetodeleteditems", "name": "moved messages to deleted items folder" }, + { "value": "new-inboxrule", "name": "created new inbox rule in outlook web app" }, + { "value": "remove delegation entry.", "name": "removed delegation entry" }, + { "value": "remove domain from company.", "name": "removed domain from company" }, + { "value": "remove member from group.", "name": "removed member from group" }, + { + "value": "remove service principal.", + "name": "removed a service principal from the directory" + }, + { + "value": "remove service principal credentials.", + "name": "removed credentials from a service principal" + }, + { "value": "remove mailboxpermission", "name": "removed delegate mailbox permissions" }, + { "value": "remove member from role.", "name": "removed a user from a directory role" }, + { "value": "remove partner from company.", "name": "removed a partner from the directory" }, + { "value": "removefolderpermissions", "name": "removed permissions from folder" }, + { "value": "reset user password.", "name": "reset user password" }, + { "value": "send", "name": "sent message" }, + { "value": "sendas", "name": "sent message using send as permissions" }, + { "value": "sendonbehalf", "name": "sent message using send on behalf permissions" }, + { "value": "set company contact information.", "name": "set company contact information" }, + { "value": "set company information.", "name": "set company information" }, + { "value": "set delegation entry.", "name": "set delegation entry" }, + { "value": "set dirsyncenabled flag.", "name": "turned on azure ad sync" }, + { "value": "set domain authentication.", "name": "set domain authentication" }, + { + "value": "set federation settings on domain.", + "name": "updated the federation settings for a domain" + }, + { + "value": "set force change user password.", + "name": "set property that forces user to change password" + }, + { "value": "set inboxrule", "name": "modified inbox rule from outlook web app" }, + { "value": "set license properties.", "name": "set license properties" }, + { "value": "set password policy.", "name": "set password policy" }, + { "value": "softdelete", "name": "deleted messages from deleted items folder" }, + { "value": "update", "name": "updated message" }, + { "value": "update user.", "name": "updated user" }, + { "value": "update group.", "name": "updated group" }, + { "value": "update domain.", "name": "updated domain" }, + { + "value": "updatecalendardelegation", + "name": "added or removed user with delegate access to calendar folder" + }, + { "value": "updatefolderpermissions", "name": "modified folder permission" }, + { "value": "updateinboxrules", "name": "updated inbox rules from outlook client" }, + { "value": "verify domain.", "name": "verified domain" }, + { "value": "verify email verified domain.", "name": "verified email verified domain" } + ], "List:LogonType": [ { "value": 0, "Membername": "Owner", "name": "The mailbox owner." }, { diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json new file mode 100644 index 000000000000..3bd7ec5e5b42 --- /dev/null +++ b/src/data/AuditLogTemplates.json @@ -0,0 +1,96 @@ +[ + { + "value": "New-InboxRule", + "name": "A new Inbox rule is created", + "template": { + "logbook": { "value": "Audit.Exchange", "name": "Exchange" }, + "conditions": [ + { + "property": "Operation", + "operator": "eq", + "Input": { "value": "new-inboxrule", "name": "created new inbox rule in outlook web app" } + } + ] + } + }, + { + "value": "New-InboxRule", + "name": "A new Inbox rule is created that forwards e-mails to the RSS feeds folder", + "template": [] + }, + { + "value": "Set-InboxRule", + "name": "A existing Inbox rule is edited", + "template": [] + }, + { + "value": "Set-InboxRule", + "name": "A existing Inbox rule is edited that forwards e-mails to the RSS feeds folder", + "template": [] + }, + { + "value": "Add member to role.", + "name": "A user has been added to an admin role", + "template": [] + }, + { + "value": "Add User.", + "name": "A user account was created", + "template": [] + }, + { + "value": "Disable account.", + "name": "A user account has been disabled", + "template": [] + }, + { + "value": "Enable account.", + "name": "A user account has been enabled", + "template": [] + }, + { + "value": "Update StsRefreshTokenValidFrom Timestamp.", + "name": "A user sessions have been revoked", + "template": [] + }, + { + "value": "Disable Strong Authentication.", + "name": "A users MFA has been disabled", + "template": [] + }, + { + "value": "Remove Member from a role.", + "name": "A user has been removed from a role", + "template": [] + }, + { + "value": "Reset user password.", + "name": "A user password has been reset", + "template": [] + }, + { + "value": "UserLoggedInFromUnknownLocation", + "name": "A user has logged in from a location not in the allowed locations list", + "template": [] + }, + { + "value": "Add service principal.", + "name": "A service principal has been created", + "template": [] + }, + { + "value": "Remove service principal.", + "name": "A service principal has been removed", + "template": [] + }, + { + "value": "badRepIP", + "name": "A user has logged in a using a known VPN, Proxy, Or anonymizer", + "template": [] + }, + { + "value": "HostedIP", + "name": "A user has logged in a using a known hosting provider IP", + "template": [] + } +] diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 8baa96022d6f..4da4807363a0 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -32,6 +32,7 @@ import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import CippButtonCard from 'src/components/contentcards/CippButtonCard' import alertList from 'src/data/alerts.json' import auditLogSchema from 'src/data/AuditLogSchema.json' +import auditLogTemplates from 'src/data/AuditLogTemplates.json' const AlertWizard = () => { const dispatch = useDispatch() @@ -50,6 +51,11 @@ const AlertWizard = () => { isSuccess, } = useListTenantQuery(tenantDomain, customerId) + const onSubmitAudit = (values) => { + console.log(values) + genericPostRequest({ path: '/api/addAuditLogMonitor', values }).then((res) => {}) + } + const onSubmitScript = (values) => { //get current time as startDate, to the closest 15 minutes in the future const startDate = new Date() @@ -79,7 +85,11 @@ const AlertWizard = () => { ...currentFormState?.values, ...recommendedRecurrence, } + const [auditFormState, setauditFormState] = useState() + const initialValuesAudit = { + ...auditFormState, + } const recurrenceOptions = [ { value: '30m', name: 'Every 30 minutes' }, { value: '1h', name: 'Every hour' }, @@ -90,72 +100,7 @@ const AlertWizard = () => { { value: '365d', name: 'Every 365 days' }, ] - const presetValues = [ - { value: 'New-InboxRule', name: 'A new Inbox rule is created' }, - { - value: 'New-InboxRule', - name: 'A new Inbox rule is created that forwards e-mails to the RSS feeds folder', - }, - - { value: 'Set-InboxRule', name: 'A existing Inbox rule is edited' }, - { - value: 'Set-InboxRule', - name: 'A existing Inbox rule is edited that forwards e-mails to the RSS feeds folder', - }, - - { - value: 'Add member to role.', - name: 'A user has been added to an admin role', - }, - { - value: 'Add User.', - name: 'A user account was created', - }, - { - value: 'Disable account.', - name: 'A user account has been disabled', - }, - { - value: 'Enable account.', - name: 'A user account has been enabled', - }, - { - value: 'Update StsRefreshTokenValidFrom Timestamp.', - name: 'A user sessions have been revoked', - }, - { - value: 'Disable Strong Authentication.', - name: 'A users MFA has been disabled', - }, - { - value: 'Remove Member from a role.', - name: 'A user has been removed from a role', - }, - { - value: 'Reset user password.', - name: 'A user password has been reset', - }, - { - value: 'UserLoggedInFromUnknownLocation', - name: 'A user has logged in from a location not in the allowed locations list', - }, - { - value: 'Add service principal.', - name: 'A service principal has been created', - }, - { - value: 'Remove service principal.', - name: 'A service principal has been removed', - }, - { - value: 'badRepIP', - name: 'A user has logged in a using a known VPN, Proxy, Or anonymizer', - }, - { - value: 'HostedIP', - name: 'A user has logged in a using a known hosting provider IP', - }, - ] + const presetValues = auditLogTemplates const getAuditLogSchema = (logbook) => { const common = auditLogSchema.Common @@ -222,8 +167,8 @@ const AlertWizard = () => { { return ( @@ -242,7 +187,7 @@ const AlertWizard = () => { From 61a0c3bc4c8cefcde24bb0853d14297d0670175e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 11 May 2024 19:30:22 +0200 Subject: [PATCH 62/92] building templates --- src/data/AuditLogTemplates.json | 12 ++++++++---- src/views/tenant/administration/AlertWizard.jsx | 16 +++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index 3bd7ec5e5b42..5ebbd20392ad 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -3,12 +3,16 @@ "value": "New-InboxRule", "name": "A new Inbox rule is created", "template": { - "logbook": { "value": "Audit.Exchange", "name": "Exchange" }, + "preset": { "value": "New-InboxRule", "label": "A new Inbox rule is created" }, + "logbook": { "value": "Audit.Exchange", "label": "Exchange" }, "conditions": [ { - "property": "Operation", - "operator": "eq", - "Input": { "value": "new-inboxrule", "name": "created new inbox rule in outlook web app" } + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "new-inboxrule", + "label": "created new inbox rule in outlook web app" + } } ] } diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 4da4807363a0..2dcde33bfdff 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -85,7 +85,7 @@ const AlertWizard = () => { ...currentFormState?.values, ...recommendedRecurrence, } - const [auditFormState, setauditFormState] = useState() + const [auditFormState, setAuditFormState] = useState() const initialValuesAudit = { ...auditFormState, @@ -133,6 +133,11 @@ const AlertWizard = () => { } } + const setAuditForm = (e) => { + const preset = presetValues.find((p) => p.value === e.value) + setAuditFormState(preset.template) + } + return ( {!queryError && ( @@ -190,6 +195,7 @@ const AlertWizard = () => { name="preset" placeholder={'Select a preset'} label="Select an alert preset, or customize your own" + onChange={(e) => setAuditForm(e)} /> @@ -220,7 +226,7 @@ const AlertWizard = () => { return ( @@ -250,7 +256,7 @@ const AlertWizard = () => { {(props) => { return ( <> - {props.values?.conditions?.[i]?.property?.value === + {props.values?.conditions?.[i]?.Property?.value === 'String' && ( { )} {props.values?.conditions?.[ i - ]?.property?.value.startsWith('List:') && ( + ]?.Property?.value.startsWith('List:') && ( Date: Sat, 11 May 2024 21:26:54 +0200 Subject: [PATCH 63/92] frontend updates --- src/data/AuditLogTemplates.json | 25 +++++++++++++++++-- .../tenant/administration/AlertWizard.jsx | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index 5ebbd20392ad..abf20a0822ce 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -18,9 +18,30 @@ } }, { - "value": "New-InboxRule", + "value": "New-InboxRuleRSS", "name": "A new Inbox rule is created that forwards e-mails to the RSS feeds folder", - "template": [] + "template": { + "preset": { + "value": "New-InboxRuleRSS", + "label": "A new Inbox rule is created that forwards e-mails to the RSS feeds folder" + }, + "logbook": { "value": "Audit.Exchange", "label": "Exchange" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "new-inboxrule", + "label": "created new inbox rule in outlook web app" + } + }, + { + "Property": { "value": "String", "label": "Path" }, + "Operator": { "value": "like", "label": "Like" }, + "Input": "*RSS*" + } + ] + } }, { "value": "Set-InboxRule", diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 2dcde33bfdff..bd7168651cbc 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -136,6 +136,7 @@ const AlertWizard = () => { const setAuditForm = (e) => { const preset = presetValues.find((p) => p.value === e.value) setAuditFormState(preset.template) + setAddedEvent(preset.template.conditions.length) } return ( From 6558f65f2268fbb9af75b8d486afb190e72bdc1c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sun, 12 May 2024 01:35:21 +0200 Subject: [PATCH 64/92] changes --- .../utilities/TenantSelectorMultiple.jsx | 10 ++++++++-- src/views/tenant/administration/AlertWizard.jsx | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/components/utilities/TenantSelectorMultiple.jsx b/src/components/utilities/TenantSelectorMultiple.jsx index 4ff2f2cb8935..63f560f7f4a0 100644 --- a/src/components/utilities/TenantSelectorMultiple.jsx +++ b/src/components/utilities/TenantSelectorMultiple.jsx @@ -4,12 +4,15 @@ import Select from 'react-select' import PropTypes from 'prop-types' const TenantSelectorMultiple = React.forwardRef( - ({ values = [], onChange = () => {}, ...rest }, ref) => { + ( + { values = [], onChange = () => {}, AllTenants = false, valueIsDomain = false, ...rest }, + ref, + ) => { const { data: tenants = [], isLoading, error, - } = useListTenantsQuery({ showAllTenantsSelector: false }) + } = useListTenantsQuery({ showAllTenantSelector: AllTenants }) let placeholder = 'Select Tenants' if (isLoading) { @@ -33,6 +36,7 @@ const TenantSelectorMultiple = React.forwardRef( options={tenants.map(({ customerId, defaultDomainName, displayName }) => ({ value: customerId, label: [displayName] + [` (${defaultDomainName})`], + fullValue: { customerId, defaultDomainName, displayName }, }))} multiple printOptions="on-focus" @@ -44,6 +48,8 @@ const TenantSelectorMultiple = React.forwardRef( TenantSelectorMultiple.propTypes = { onChange: PropTypes.func, + AllTenants: PropTypes.bool, + valueIsDomain: PropTypes.bool, values: PropTypes.arrayOf(PropTypes.string).isRequired, } diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index bd7168651cbc..f03c2f269bfa 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -44,6 +44,7 @@ const AlertWizard = () => { const [alertType, setAlertType] = useState(false) const [recommendedRecurrence, setRecommendedRecurrence] = useState() const [currentFormState, setCurrentFormState] = useState() + const [selectedTenant, setSelectedTenant] = useState([]) const { data: tenant = {}, isFetching, @@ -52,8 +53,7 @@ const AlertWizard = () => { } = useListTenantQuery(tenantDomain, customerId) const onSubmitAudit = (values) => { - console.log(values) - genericPostRequest({ path: '/api/addAuditLogMonitor', values }).then((res) => {}) + genericPostRequest({ path: '/api/addAlert', values }).then((res) => {}) } const onSubmitScript = (values) => { @@ -88,6 +88,7 @@ const AlertWizard = () => { const [auditFormState, setAuditFormState] = useState() const initialValuesAudit = { + tenantFilter: [...selectedTenant], ...auditFormState, } const recurrenceOptions = [ @@ -168,7 +169,11 @@ const AlertWizard = () => { Select the tenants you want to include in this Alert. - + setSelectedTenant(e)} + AllTenants={true} + valueisDomain={true} + /> @@ -307,6 +312,11 @@ const AlertWizard = () => { )} + {postResults.isSuccess && ( + +
  • {postResults.data.Results}
  • +
    + )} From b5c46b85057a7f01f85a5e8a3c09174c07d93dc8 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sun, 12 May 2024 20:23:39 +0200 Subject: [PATCH 65/92] Fix input bug. --- src/data/AuditLogSchema.json | 4 ++-- src/views/tenant/administration/AlertWizard.jsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/data/AuditLogSchema.json b/src/data/AuditLogSchema.json index 5ad677a63f51..e90a1e41866f 100644 --- a/src/data/AuditLogSchema.json +++ b/src/data/AuditLogSchema.json @@ -12,11 +12,11 @@ "ObjectId": "String", "UserId": "String", "ClientIP": "String", - "IPDetectedbyCIPP": "String", "Username": "String", "CIPPGeoLocation": "List:countryList", "CIPPBadRepIP": "String", - "CIPPHostedIP": "String" + "CIPPHostedIP": "String", + "CIPPIPDetected": "String" }, "Audit.Exchange": { "Id": "Combination GUID", diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index f03c2f269bfa..7b1e8c6725b0 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -265,7 +265,7 @@ const AlertWizard = () => { {props.values?.conditions?.[i]?.Property?.value === 'String' && ( From d75a2370ebf9e8da7d45ca64033f5227e23f3150 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sun, 12 May 2024 23:25:30 +0200 Subject: [PATCH 66/92] added multi select --- src/data/AuditLogSchema.json | 12 +- src/data/AuditLogTemplates.json | 144 ++++++++++++++---- .../tenant/administration/AlertWizard.jsx | 3 + 3 files changed, 129 insertions(+), 30 deletions(-) diff --git a/src/data/AuditLogSchema.json b/src/data/AuditLogSchema.json index e90a1e41866f..0f605f0f7d89 100644 --- a/src/data/AuditLogSchema.json +++ b/src/data/AuditLogSchema.json @@ -49,12 +49,12 @@ "ClientIPAddress": "String", "ClientMachinename": "String", "ClientProcessname": "String", - "ClientVersion": "String" + "ClientVersion": "String", + "MoveToFolder": "String" }, "Audit.AzureActiveDirectory": { "AzureActiveDirectoryEventType": "List:AzureActiveDirectoryEventType", - "ExtendedProperties": "Common.namevaluePair", - "ModifiedProperties": "Common.ModifiedProperty", + "AccountEnabled": "String", "Actor": "List:IdentityTypevaluePair", "ActorContextId": "String", "ActorIpAddress": "String", @@ -143,7 +143,11 @@ { "value": "updatefolderpermissions", "name": "modified folder permission" }, { "value": "updateinboxrules", "name": "updated inbox rules from outlook client" }, { "value": "verify domain.", "name": "verified domain" }, - { "value": "verify email verified domain.", "name": "verified email verified domain" } + { "value": "verify email verified domain.", "name": "verified email verified domain" }, + { + "value": "Update StsRefreshTokenValidFrom Timestamp.", + "name": "Update StsRefreshTokenValidFrom Timestamp." + } ], "List:LogonType": [ { "value": 0, "Membername": "Owner", "name": "The mailbox owner." }, diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index abf20a0822ce..06088b6a948c 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -36,9 +36,9 @@ } }, { - "Property": { "value": "String", "label": "Path" }, + "Property": { "value": "String", "label": "MoveToFolder" }, "Operator": { "value": "like", "label": "Like" }, - "Input": "*RSS*" + "Input": { "value": "*RSS*" } } ] } @@ -46,37 +46,69 @@ { "value": "Set-InboxRule", "name": "A existing Inbox rule is edited", - "template": [] + "template": { + "preset": { "value": "Set-InboxRule", "label": "A existing Inbox rule is edited" }, + "logbook": { "value": "Audit.Exchange", "label": "Exchange" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "set-inboxrule", + "label": "Updated inbox rule in outlook web app" + } + } + ] + } }, { - "value": "Set-InboxRule", + "value": "Set-InboxRuleRSS", "name": "A existing Inbox rule is edited that forwards e-mails to the RSS feeds folder", - "template": [] + "template": { + "preset": { "value": "Set-InboxRuleRSS", "label": "A existing Inbox rule is edited" }, + "logbook": { "value": "Audit.Exchange", "label": "Exchange" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "set-inboxrule", + "label": "Updated inbox rule in outlook web app" + } + }, + { + "Property": { "value": "String", "label": "MoveToFolder" }, + "Operator": { "value": "like", "label": "Like" }, + "Input": { "value": "*RSS*" } + } + ] + } }, { "value": "Add member to role.", "name": "A user has been added to an admin role", "template": [] }, - { - "value": "Add User.", - "name": "A user account was created", - "template": [] - }, - { - "value": "Disable account.", - "name": "A user account has been disabled", - "template": [] - }, - { - "value": "Enable account.", - "name": "A user account has been enabled", - "template": [] - }, { "value": "Update StsRefreshTokenValidFrom Timestamp.", "name": "A user sessions have been revoked", - "template": [] + "template": { + "preset": { + "value": "Update StsRefreshTokenValidFrom Timestamp.", + "label": "A user sessions have been revoked" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "Update StsRefreshTokenValidFrom Timestamp.", + "label": "Update StsRefreshTokenValidFrom Timestamp." + } + } + ] + } }, { "value": "Disable Strong Authentication.", @@ -91,12 +123,40 @@ { "value": "Reset user password.", "name": "A user password has been reset", - "template": [] + "template": { + "preset": { + "value": "A user password has been reset", + "label": "Reset user password." + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "Reset user password.", + "label": "Reset user password." + } + } + ] + } }, { "value": "UserLoggedInFromUnknownLocation", - "name": "A user has logged in from a location not in the allowed locations list", - "template": [] + "name": "A user has logged in from a location not in the input list", + "template": { + "preset": { + "value": "UserLoggedInFromUnknownLocation", + "label": "A user has logged in from a location not in the input list" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:countryList", "label": "CIPPGeoLocation", "multi": true }, + "Operator": { "value": "NotIn", "label": "Not In" } + } + ] + } }, { "value": "Add service principal.", @@ -111,11 +171,43 @@ { "value": "badRepIP", "name": "A user has logged in a using a known VPN, Proxy, Or anonymizer", - "template": [] + "template": { + "preset": { + "value": "badRepIP", + "label": "A user has logged in a using a known VPN, Proxy, Or anonymizer" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "String", "label": "CIPPBadRepIP" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "true", + "label": "true" + } + } + ] + } }, { "value": "HostedIP", "name": "A user has logged in a using a known hosting provider IP", - "template": [] + "template": { + "preset": { + "value": "HostedIP", + "label": "A user has logged in a using a known hosting provider IP" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "String", "label": "CIPPHostedIP" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "true", + "label": "true" + } + } + ] + } } ] diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 7b1e8c6725b0..7b1a5f593293 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -279,6 +279,9 @@ const AlertWizard = () => { props.values?.conditions?.[i]?.Property?.value ] } + multi={ + props.values?.conditions?.[i]?.Property?.multi + } name={`conditions.${i}.Input`} placeholder={'Select an input from the list'} label="Input" From 8bd095492948bb793e19cdf65236032615e57cb4 Mon Sep 17 00:00:00 2001 From: rvdwegen Date: Sun, 12 May 2024 23:40:38 +0200 Subject: [PATCH 67/92] Add action button to remove GA from GDAP relations --- .../administration/ListGDAPRelationships.jsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/views/tenant/administration/ListGDAPRelationships.jsx b/src/views/tenant/administration/ListGDAPRelationships.jsx index c463797c16c9..11ae56e89e33 100644 --- a/src/views/tenant/administration/ListGDAPRelationships.jsx +++ b/src/views/tenant/administration/ListGDAPRelationships.jsx @@ -111,6 +111,14 @@ const Actions = (row, rowIndex, formatExtraData) => { modalUrl: `/api/ExecAutoExtendGDAP?ID=${row.id}`, modalMessage: 'Are you sure you want to enable auto-extend for this relationship', }, + { + label: 'Remove Global Administrator from Relationship', + color: 'danger', + modal: true, + modalUrl: `/api/ExecGDAPRemoveGArole?&GDAPID=${row.id}`, + modalMessage: + 'Are you sure you want to remove Global Administrator from this relationship?', + }, { label: 'Terminate Relationship', color: 'danger', @@ -218,6 +226,13 @@ const GDAPRelationships = () => { tableProps: { selectableRows: true, actionsList: [ + { + label: 'Remove Global Administrator from Relationship', + modal: true, + modalUrl: `/api/ExecGDAPRemoveGArole?&GDAPID=!id`, + modalMessage: + 'Are you sure you want to remove Global Administrator from these relationship(s)?', + }, { label: 'Terminate Relationship', modal: true, From 6de5f4cedd4f8c8e629dfb91565da9accbdb0438 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 00:02:42 +0200 Subject: [PATCH 68/92] updated schemas --- src/data/AuditLogSchema.json | 1 + src/data/AuditLogTemplates.json | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/data/AuditLogSchema.json b/src/data/AuditLogSchema.json index 0f605f0f7d89..1051d7b758cc 100644 --- a/src/data/AuditLogSchema.json +++ b/src/data/AuditLogSchema.json @@ -69,6 +69,7 @@ "LogonError": "String" }, "List:Operation": [ + { "value": "UserLoggedIn", "name": "A user logged in" }, { "value": "accessed mailbox items", "name": "accessed mailbox items" }, { "value": "add delegation entry.", "name": "added delegation entry" }, { "value": "add domain to company.", "name": "added domain to company" }, diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index 06088b6a948c..f5293ed718ff 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -151,6 +151,14 @@ }, "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "UserLoggedIn", + "label": "A user logged in" + } + }, { "Property": { "value": "List:countryList", "label": "CIPPGeoLocation", "multi": true }, "Operator": { "value": "NotIn", "label": "Not In" } @@ -178,6 +186,14 @@ }, "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "UserLoggedIn", + "label": "A user logged in" + } + }, { "Property": { "value": "String", "label": "CIPPBadRepIP" }, "Operator": { "value": "EQ", "label": "Equals" }, @@ -199,6 +215,14 @@ }, "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals" }, + "Input": { + "value": "UserLoggedIn", + "label": "A user logged in" + } + }, { "Property": { "value": "String", "label": "CIPPHostedIP" }, "Operator": { "value": "EQ", "label": "Equals" }, From 3f171f03958627ce8117bb75cb55d44048d7cd85 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 01:29:22 +0200 Subject: [PATCH 69/92] add option for actions --- .../tenant/administration/AlertWizard.jsx | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 7b1a5f593293..10c9df1199e9 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -140,6 +140,16 @@ const AlertWizard = () => { setAddedEvent(preset.template.conditions.length) } + const dovalues = [ + //{ value: 'cippcommand', label: 'Execute a CIPP Command' }, + { value: 'becremediate', name: 'Execute a BEC Remediate' }, + { value: 'disableuser', name: 'Disable the user in the log entry' }, + // { value: 'generatelog', label: 'Generate a log entry' }, + { value: 'generatemail', name: 'Generate an email' }, + { value: 'generatePSA', name: 'Generate a PSA ticket' }, + { value: 'generateWebhook', name: 'Generate a webhook' }, + ] + return ( {!queryError && ( @@ -321,6 +331,17 @@ const AlertWizard = () => { )} + + + + + From b19c7d23afed5e7e4185f8ab996c0ff5ef35f174 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 01:54:16 +0200 Subject: [PATCH 70/92] improved wizard interface --- .../tenant/administration/AlertWizard.jsx | 59 +++++++------------ 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 10c9df1199e9..43a9acbc0593 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -1,18 +1,5 @@ -import React, { useEffect, useState } from 'react' -import { - CBadge, - CButton, - CCallout, - CCard, - CCardBody, - CCardHeader, - CCardTitle, - CCol, - CForm, - CRow, - CSpinner, - CWidgetStatsA, -} from '@coreui/react' +import React, { useState } from 'react' +import { CBadge, CButton, CCallout, CCol, CForm, CRow, CSpinner } from '@coreui/react' import useQuery from 'src/hooks/useQuery' import { useDispatch, useSelector } from 'react-redux' import { Field, Form, FormSpy } from 'react-final-form' @@ -21,7 +8,6 @@ import { TenantSelector, TenantSelectorMultiple } from 'src/components/utilities import { Condition, RFFCFormInput, - RFFCFormRadio, RFFCFormSwitch, RFFSelectSearch, } from 'src/components/forms/RFFComponents' @@ -33,24 +19,16 @@ import CippButtonCard from 'src/components/contentcards/CippButtonCard' import alertList from 'src/data/alerts.json' import auditLogSchema from 'src/data/AuditLogSchema.json' import auditLogTemplates from 'src/data/AuditLogTemplates.json' +import Skeleton from 'react-loading-skeleton' const AlertWizard = () => { - const dispatch = useDispatch() - let query = useQuery() const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) - const customerId = query.get('customerId') - const [queryError, setQueryError] = useState(false) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() const [alertType, setAlertType] = useState(false) const [recommendedRecurrence, setRecommendedRecurrence] = useState() const [currentFormState, setCurrentFormState] = useState() const [selectedTenant, setSelectedTenant] = useState([]) - const { - data: tenant = {}, - isFetching, - error, - isSuccess, - } = useListTenantQuery(tenantDomain, customerId) + const { data: tenant = {}, isFetching, error, isSuccess } = useListTenantQuery(tenantDomain) const onSubmitAudit = (values) => { genericPostRequest({ path: '/api/addAlert', values }).then((res) => {}) @@ -152,7 +130,8 @@ const AlertWizard = () => { return ( - {!queryError && ( + {isFetching && } + {!isFetching && ( <> @@ -200,7 +179,7 @@ const AlertWizard = () => { titleType="big" CardButton={ - Save Alert + {postResults.isFetching && } Save Alert } > @@ -325,23 +304,25 @@ const AlertWizard = () => { )} + + + + + {postResults.isSuccess && (
  • {postResults.data.Results}
  • )}
    - - - - - From 14d21dc6a80ae10cd6617f28f962cc61bf5e149c Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 16:23:16 +0200 Subject: [PATCH 71/92] added validation to required fields. --- src/components/tables/CellBadge.jsx | 28 +- src/data/AuditLogTemplates.json | 22 +- .../tenant/administration/AlertWizard.jsx | 12 +- .../tenant/administration/ListAlertsQueue.jsx | 293 +++--------------- 4 files changed, 81 insertions(+), 274 deletions(-) diff --git a/src/components/tables/CellBadge.jsx b/src/components/tables/CellBadge.jsx index ae6b948ce83f..03552866c817 100644 --- a/src/components/tables/CellBadge.jsx +++ b/src/components/tables/CellBadge.jsx @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' -import { CBadge } from '@coreui/react' +import { CBadge, CCol, CRow } from '@coreui/react' export const CellBadge = ({ label = '', color = '', children, ...rest }) => { //Create a case select, and return the color based on the label @@ -19,14 +19,28 @@ export const CellBadge = ({ label = '', color = '', children, ...rest }) => { break case 'running': color = 'primary' + break } + //if a label contains a comma, split it, and return multiple badges, if not, return one badge. force the badges to be on their own line - return ( - - {label} - {children} - - ) + if (label.includes(',')) { + const labels = label.split(',') + return labels.map((label, idx) => ( + <> + + {label} + {children} + + + )) + } else { + return ( + + {label} + {children} + + ) + } } CellBadge.propTypes = { diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index f5293ed718ff..723b7c39dd34 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -8,7 +8,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "new-inboxrule", "label": "created new inbox rule in outlook web app" @@ -29,7 +29,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "new-inboxrule", "label": "created new inbox rule in outlook web app" @@ -52,7 +52,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "set-inboxrule", "label": "Updated inbox rule in outlook web app" @@ -70,7 +70,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "set-inboxrule", "label": "Updated inbox rule in outlook web app" @@ -101,7 +101,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "Update StsRefreshTokenValidFrom Timestamp.", "label": "Update StsRefreshTokenValidFrom Timestamp." @@ -132,7 +132,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "Reset user password.", "label": "Reset user password." @@ -153,7 +153,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "UserLoggedIn", "label": "A user logged in" @@ -188,7 +188,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "UserLoggedIn", "label": "A user logged in" @@ -196,7 +196,7 @@ }, { "Property": { "value": "String", "label": "CIPPBadRepIP" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "true", "label": "true" @@ -217,7 +217,7 @@ "conditions": [ { "Property": { "value": "List:Operation", "label": "Operation" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "UserLoggedIn", "label": "A user logged in" @@ -225,7 +225,7 @@ }, { "Property": { "value": "String", "label": "CIPPHostedIP" }, - "Operator": { "value": "EQ", "label": "Equals" }, + "Operator": { "value": "EQ", "label": "Equals to" }, "Input": { "value": "true", "label": "true" diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx index 43a9acbc0593..2c3bf20bf0cf 100644 --- a/src/views/tenant/administration/AlertWizard.jsx +++ b/src/views/tenant/administration/AlertWizard.jsx @@ -20,6 +20,7 @@ import alertList from 'src/data/alerts.json' import auditLogSchema from 'src/data/AuditLogSchema.json' import auditLogTemplates from 'src/data/AuditLogTemplates.json' import Skeleton from 'react-loading-skeleton' +import { required } from 'src/validators' const AlertWizard = () => { const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) @@ -204,6 +205,7 @@ const AlertWizard = () => { name="logbook" placeholder={'Select a log source'} label="Select the log you which to receive the alert for" + validate={required} /> @@ -224,6 +226,7 @@ const AlertWizard = () => { name={`conditions.${i}.Property`} placeholder={'Select a property to alert on'} label="When property" + validate={required} /> ) }} @@ -232,9 +235,9 @@ const AlertWizard = () => { { name={`conditions.${i}.Operator`} placeholder={'Select a command'} label="is" + validate={required} /> @@ -257,6 +261,7 @@ const AlertWizard = () => { name={`conditions.${i}.Input.value`} placeholder={'Select a command'} label={`Input`} + validate={required} /> )} {props.values?.conditions?.[ @@ -274,6 +279,7 @@ const AlertWizard = () => { name={`conditions.${i}.Input`} placeholder={'Select an input from the list'} label="Input" + validate={required} /> )} @@ -372,6 +378,7 @@ const AlertWizard = () => { name="command" placeholder={'Select a command'} label="What alerting script should run" + validate={required} /> @@ -386,6 +393,7 @@ const AlertWizard = () => { name="input" label={props.values.command.value.inputLabel} placeholder="Enter a value" + validate={required} /> ) }} diff --git a/src/views/tenant/administration/ListAlertsQueue.jsx b/src/views/tenant/administration/ListAlertsQueue.jsx index abce88eca036..7aeccd561a42 100644 --- a/src/views/tenant/administration/ListAlertsQueue.jsx +++ b/src/views/tenant/administration/ListAlertsQueue.jsx @@ -1,279 +1,57 @@ import React, { useState } from 'react' -import { CButton, CCallout, CCol, CForm, CRow, CSpinner, CTooltip } from '@coreui/react' +import { CCol, CRow } from '@coreui/react' import { useSelector } from 'react-redux' -import { Field, Form, FormSpy } from 'react-final-form' -import { RFFCFormInput, RFFCFormSwitch } from 'src/components/forms' -import { - useGenericGetRequestQuery, - useLazyGenericGetRequestQuery, - useLazyGenericPostRequestQuery, -} from 'src/store/api/app' -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons' -import { CippContentCard, CippPage, CippPageList } from 'src/components/layout' -import { CellTip } from 'src/components/tables/CellGenericFormat' -import 'react-datepicker/dist/react-datepicker.css' -import { CippActionsOffcanvas, ModalService, TenantSelector } from 'src/components/utilities' -import arrayMutators from 'final-form-arrays' -const alertsList = [ - { name: 'MFAAlertUsers', label: 'Alert on users without any form of MFA' }, - { name: 'MFAAdmins', label: 'Alert on admins without any form of MFA' }, - { - name: 'NoCAConfig', - label: - 'Alert on tenants without a Conditional Access policy, while having Conditional Access licensing available.', - }, - { name: 'AdminPassword', label: 'Alert on changed admin Passwords' }, - { - name: 'QuotaUsed', - label: 'Alert on % mailbox quota used', - requiresInput: true, - inputLabel: 'Enter quota percentage', - inputName: 'QuotaUsedQuota', - }, - { - name: 'SharePointQuota', - label: 'Alert on % SharePoint quota used', - requiresInput: true, - inputLabel: 'Enter quota percentage', - inputName: 'SharePointQuotaQuota', - }, - { name: 'ExpiringLicenses', label: 'Alert on licenses expiring in 30 days' }, - { name: 'NewAppApproval', label: 'Alert on new apps in the application approval list' }, - { name: 'SecDefaultsUpsell', label: 'Alert on Security Defaults automatic enablement' }, - { - name: 'DefenderStatus', - label: 'Alert if Defender is not running (Tenant must be on-boarded in Lighthouse)', - }, - { - name: 'DefenderMalware', - label: 'Alert on Defender Malware found (Tenant must be on-boarded in Lighthouse)', - }, - { name: 'UnusedLicenses', label: 'Alert on unused licenses' }, - { name: 'OverusedLicenses', label: 'Alert on overused licenses' }, - { name: 'AppSecretExpiry', label: 'Alert on expiring application secrets' }, - { name: 'ApnCertExpiry', label: 'Alert on expiring APN certificates' }, - { name: 'VppTokenExpiry', label: 'Alert on expiring VPP tokens' }, - { name: 'DepTokenExpiry', label: 'Alert on expiring DEP tokens' }, -] +import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' + +import { CippPage, CippPageList } from 'src/components/layout' +import { CellTip, cellGenericFormatter } from 'src/components/tables/CellGenericFormat' +import 'react-datepicker/dist/react-datepicker.css' +import { CellBadge, cellBadgeFormatter } from 'src/components/tables' +import { TitleButton } from 'src/components/buttons' const ListClassicAlerts = () => { const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery() - - const Offcanvas = (row, rowIndex, formatExtraData) => { - const [ocVisible, setOCVisible] = useState(false) - - const handleDeleteSchedule = (apiurl, message) => { - ModalService.confirm({ - title: 'Confirm', - body:
    {message}
    , - onConfirm: () => - ExecuteGetRequest({ path: apiurl }).then((res) => { - setRefreshState(res.requestId) - }), - confirmLabel: 'Continue', - cancelLabel: 'Cancel', - }) - } - let jsonResults - try { - jsonResults = JSON.parse(row) - } catch (error) { - jsonResults = row - } - - return ( - <> - - setOCVisible(true)}> - - - - - - handleDeleteSchedule( - `/api/RemoveQueuedAlert?&ID=${row.tenantId}`, - 'Do you want to delete the queued alert?', - ) - } - size="sm" - variant="ghost" - color="danger" - > - - - - ({ - label: key, - value: - typeof row[key] === 'boolean' ? ( - row[key] ? ( - - ) : ( - - ) - ) : ( - row[key] - ), - }))} - placement="end" - visible={ocVisible} - id={row.id} - hideFunction={() => setOCVisible(false)} - /> - - ) - } - const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) const [refreshState, setRefreshState] = useState(false) const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() - const onSubmit = (values) => { - Object.keys(values).filter(function (x) { - if (values[x] === null || values[x] === 0) { - delete values[x] - } - return null - }) - values['tenantFilter'] = tenantDomain - values['SetAlerts'] = true - genericPostRequest({ path: '/api/AddAlert', values: values }).then((res) => { - setRefreshState(res.requestId) - }) - } - const { data: currentlySelectedAlerts = [], isLoading: isLoadingCurrentAlerts } = - useGenericGetRequestQuery({ - path: `api/ListAlertsQueue?TenantFilter=${tenantDomain}&RefreshGuid=${refreshState}`, - }) const columns = [ { - name: 'Tenant Name', - selector: (row) => row['tenantName'], + name: 'Tenant(s)', + selector: (row) => row['Tenants'], sortable: true, - cell: (row) => CellTip(row['tenantName']), - exportSelector: 'tenantName', + cell: (row) => CellTip(row['Tenants']), + exportSelector: 'Tenants', }, { - name: 'Tenant ID', - selector: (row) => row['tenantId'], + name: 'Events', + selector: (row) => row['Conditions'], sortable: true, - cell: (row) => CellTip(row['tenantId']), - exportSelector: 'tenantId', + cell: (row) => CellTip(row['Conditions']), + exportSelector: 'Conditions', }, { - name: 'Actions', - cell: Offcanvas, - maxWidth: '80px', + name: 'Actions to take', + selector: (row) => row['Actions'], + sortable: true, + cell: cellBadgeFormatter({ color: 'info' }), + exportSelector: 'Actions', + }, + { + name: 'Event Type', + selector: (row) => row['EventType'], + sortable: true, + cell: cellBadgeFormatter({ color: 'info' }), + exportSelector: 'EventType', }, ] - const initialValues = currentlySelectedAlerts.filter((x) => x.tenantName === tenantDomain)[0] - const allTenantsAlert = currentlySelectedAlerts.find( - (tenant) => tenant.tenantName === 'AllTenants', - ) - function getLabel(item) { - if (typeof allTenantsAlert === 'object' && allTenantsAlert !== null) { - if (allTenantsAlert[`${item}`]) { - return `* Enabled via All Tenants` - } - } - return '' - } return ( <> - - - { - return ( - -

    - Classic Alerts are sent every 15 minutes, with a maximum of 1 unique alert - per 24 hours. These alerts do not use the Alert Rules Engine. -

    - {isLoadingCurrentAlerts && } - - - - {(props) => } - - - -
    - {alertsList.map((alert, index) => ( - - - {alert.requiresInput && ( - - {({ values }) => { - if (values[alert.name]) { - return ( - - ) - } - return null - }} - - )} - - ))} -
    - - - - Set Alerts - {postResults.isFetching && ( - - )} - - - - {postResults.isSuccess && ( - -
  • {postResults.data.Results}
  • -
    - )} - {getResults.isFetching && ( - - Loading - - )} - {getResults.isSuccess && ( - {getResults.data?.Results} - )} - {getResults.isError && ( - - Could not connect to API: {getResults.error.message} - - )} -
    - ) - }} - /> -
    -
    - + { helpContext: 'https://google.com', }} title="Alerts List" + titleButton={ + + } tenantSelector={false} datatable={{ tableProps: { selectableRows: true, actionsList: [ { - label: 'Delete task', + label: 'Delete Alert', modal: true, - modalUrl: `/api/RemoveQueuedAlert?&ID=!tenantId`, + modalUrl: `/api/RemoveQueuedAlert?&ID=!RowKey&EventType=!EventType&RefreshGuid=${refreshState}`, modalMessage: 'Do you want to delete this job?', }, ], }, columns, - reportName: `Scheduled-Jobs`, + reportName: `Alerts`, path: `/api/ListAlertsQueue?RefreshGuid=${refreshState}`, }} /> From c09dc4f35c34ce92b5ce016b70015f7ef0584363 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 16:30:01 +0200 Subject: [PATCH 72/92] Change nav items(Down with classic alerts!) --- src/_nav.jsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/_nav.jsx b/src/_nav.jsx index b0ec445ccd13..2f99dffd0953 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -129,14 +129,9 @@ const _nav = [ }, { component: CNavItem, - name: 'Alerts (Classic)', + name: 'Alerts', to: '/tenant/administration/alertsqueue', }, - { - component: CNavItem, - name: 'Alert Rules', - to: '/tenant/administration/AlertRules', - }, { component: CNavItem, name: 'Enterprise Applications', From d346a2041bbe60015a33232023cf4e7146bb155d Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 13 May 2024 10:50:10 -0400 Subject: [PATCH 73/92] Fix recent job load error for single task --- src/components/utilities/CippTableOffcanvas.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/utilities/CippTableOffcanvas.jsx b/src/components/utilities/CippTableOffcanvas.jsx index bc603ecdfda4..561d0e6839b1 100644 --- a/src/components/utilities/CippTableOffcanvas.jsx +++ b/src/components/utilities/CippTableOffcanvas.jsx @@ -14,7 +14,7 @@ function CippTableOffcanvas({ tableProps, data = null, }) { - if (data !== null && data !== undefined) { + if (Array.isArray(data) && data !== null && data !== undefined) { if (!Array.isArray(data) && typeof data === 'object') { data = Object.keys(data).map((key) => { return { @@ -53,7 +53,7 @@ function CippTableOffcanvas({ hideFunction={hideFunction} > <> - {data !== null && data !== undefined ? ( + {Array.isArray(data) && data !== null && data !== undefined ? ( ) : ( From 5d81b46fea1a0126f32c06d5bcf716f1e8198698 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 18:26:55 +0200 Subject: [PATCH 74/92] added repeats every --- src/views/tenant/administration/ListAlertsQueue.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/views/tenant/administration/ListAlertsQueue.jsx b/src/views/tenant/administration/ListAlertsQueue.jsx index 7aeccd561a42..7efe849c13a4 100644 --- a/src/views/tenant/administration/ListAlertsQueue.jsx +++ b/src/views/tenant/administration/ListAlertsQueue.jsx @@ -38,6 +38,13 @@ const ListClassicAlerts = () => { cell: cellBadgeFormatter({ color: 'info' }), exportSelector: 'Actions', }, + { + name: 'Repeats every', + selector: (row) => row['RepeatsEvery'], + sortable: true, + cell: (row) => CellTip(row['RepeatsEvery']), + exportSelector: 'RepeatsEvery', + }, { name: 'Event Type', selector: (row) => row['EventType'], From 56d17ffd6c342b29c8f85ac9510acdc8c68ce2a8 Mon Sep 17 00:00:00 2001 From: Esco Date: Mon, 13 May 2024 13:38:17 +0200 Subject: [PATCH 75/92] Added branding standard --- src/data/standards.json | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/data/standards.json b/src/data/standards.json index afb7048f77be..92252d5a36ad 100644 --- a/src/data/standards.json +++ b/src/data/standards.json @@ -60,6 +60,57 @@ "remediate": false } }, + { + "name": "standards.Branding", + "cat": "Global Standards", + "tag": ["lowimpact"], + "helpText": "Sets the branding for the tenant. This includes the login page, and the Office 365 portal.", + "addedComponent": [ + { + "type": "input", + "name": "standards.Branding.signInPageText", + "label": "Sign-in page text" + }, + { + "type": "input", + "name": "standards.Branding.usernameHintText", + "label": "Username hint Text" + }, + { + "type": "boolean", + "name": "standards.Branding.hideAccountResetCredentials", + "label": "Hide self-service password reset" + }, + { + "type": "Select", + "label": "Visual Template", + "name": "standards.Branding.layoutTemplateType", + "values": [ + { + "label": "Full-screen background", + "value": "default" + }, + { + "label": "Parial-screen background", + "value": "verticalSplit" + } + ] + }, + { + "type": "boolean", + "name": "standards.Branding.isHeaderShown", + "label": "Show header" + }, + { + "type":"boolean", + "name":"standards.Branding.isFooterShown", + "label":"Show footer" + } + ], + "label": "Set branding for the tenant", + "impact": "Low Impact", + "impactColour": "info" + }, { "name": "standards.EnableCustomerLockbox", "cat": "Global Standards", From d265bbaf844dda43a0b084f5d03fb925670c06c7 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 13 May 2024 14:10:30 -0400 Subject: [PATCH 76/92] Improve Extension Mappings --- .../SettingsExtensionMappings.jsx | 122 ++++++++++++------ 1 file changed, 85 insertions(+), 37 deletions(-) diff --git a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx index 8f8ebed14efc..f2deb9d187be 100644 --- a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx +++ b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx @@ -41,6 +41,9 @@ export function SettingsExtensionMappings() { setHaloExtensionconfig({ path: 'api/ExecExtensionMapping?AddMapping=Halo', values: { mappings: originalFormat }, + }).then(() => { + listHaloBackend({ path: 'api/ExecExtensionMapping?List=Halo' }) + setMappingValue({}) }) } const onNinjaOrgsSubmit = () => { @@ -52,6 +55,9 @@ export function SettingsExtensionMappings() { setNinjaOrgsExtensionconfig({ path: 'api/ExecExtensionMapping?AddMapping=NinjaOrgs', values: { mappings: originalFormat }, + }).then(() => { + listNinjaOrgsBackend({ path: 'api/ExecExtensionMapping?List=NinjaOrgs' }) + setMappingValue({}) }) } @@ -68,7 +74,6 @@ export function SettingsExtensionMappings() { const onNinjaFieldsSubmit = (values) => { setNinjaFieldsExtensionconfig({ path: 'api/ExecExtensionMapping?AddMapping=NinjaFields', - values: { mappings: values }, }) } @@ -91,8 +96,11 @@ export function SettingsExtensionMappings() { }, //filter out any undefined values ).filter((item) => item !== undefined) - setHaloMappingsArray((currentHaloMappings) => [...currentHaloMappings, ...newMappings]) - + setHaloMappingsArray((currentHaloMappings) => [...currentHaloMappings, ...newMappings]).then( + () => { + listHaloBackend({ path: 'api/ExecExtensionMapping?List=Halo' }) + }, + ) setHaloAutoMap(true) } @@ -235,7 +243,7 @@ export function SettingsExtensionMappings() { @@ -253,7 +261,7 @@ export function SettingsExtensionMappings() { } > - {listBackendHaloResult.isFetching ? ( + {listBackendHaloResult.isFetching && listBackendHaloResult.isUninitialized ? ( ) : ( ({ + values={listBackendHaloResult.data?.Tenants.filter((tenant) => { + return !Object.keys(listBackendHaloResult.data?.Mappings).includes( + tenant.customerId, + ) + }).map((tenant) => ({ name: tenant.displayName, value: tenant.customerId, }))} onChange={(e) => { setMappingArray(e.value) }} + isLoading={listBackendHaloResult.isFetching} /> @@ -295,29 +308,43 @@ export function SettingsExtensionMappings() { ({ + name="halo_client" + values={listBackendHaloResult.data?.HaloClients.filter((client) => { + return !Object.values(listBackendHaloResult.data?.Mappings) + .map((value) => { + return value.value + }) + .includes(client.value) + }).map((client) => ({ name: client.name, value: client.value, }))} onChange={(e) => setMappingValue(e)} placeholder="Select a HaloPSA Client" + isLoading={listBackendHaloResult.isFetching} /> - //set the new mapping in the array - setHaloMappingsArray([ - ...haloMappingsArray, - { - Tenant: listBackendHaloResult.data?.Tenants.find( - (tenant) => tenant.customerId === mappingArray, - ), - haloName: mappingValue.label, - haloId: mappingValue.value, - }, - ]) - } + onClick={() => { + if ( + mappingValue.value !== undefined && + Object.values(haloMappingsArray) + .map((item) => item.haloId) + .includes(mappingValue.value) === false + ) { + //set the new mapping in the array + setHaloMappingsArray([ + ...haloMappingsArray, + { + Tenant: listBackendHaloResult.data?.Tenants.find( + (tenant) => tenant.customerId === mappingArray, + ), + haloName: mappingValue.label, + haloId: mappingValue.value, + }, + ]) + } + }} className={`my-4 circular-button`} title={'+'} > @@ -381,7 +408,7 @@ export function SettingsExtensionMappings() { } > - {listBackendNinjaOrgsResult.isFetching ? ( + {listBackendNinjaOrgsResult.isFetching && listBackendNinjaOrgsResult.isUninitialized ? ( ) : ( ({ + values={listBackendNinjaOrgsResult.data?.Tenants.filter((tenant) => { + return !Object.keys( + listBackendNinjaOrgsResult.data?.Mappings, + ).includes(tenant.customerId) + }).map((tenant) => ({ name: tenant.displayName, value: tenant.customerId, }))} onChange={(e) => { setMappingArray(e.value) }} + isLoading={listBackendNinjaOrgsResult.isFetching} /> @@ -423,29 +455,45 @@ export function SettingsExtensionMappings() { ({ + name="ninja_org" + values={listBackendNinjaOrgsResult.data?.NinjaOrgs.filter( + (client) => { + return !Object.values(listBackendNinjaOrgsResult.data?.Mappings) + .map((value) => { + return value.value + }) + .includes(client.value.toString()) + }, + ).map((client) => ({ name: client.name, value: client.value, }))} onChange={(e) => setMappingValue(e)} placeholder="Select a NinjaOne Organization" + isLoading={listBackendNinjaOrgsResult.isFetching} /> + onClick={() => { //set the new mapping in the array - setNinjaMappingsArray([ - ...ninjaMappingsArray, - { - Tenant: listBackendNinjaOrgsResult.data?.Tenants.find( - (tenant) => tenant.customerId === mappingArray, - ), - ninjaName: mappingValue.label, - ninjaId: mappingValue.value, - }, - ]) - } + if ( + mappingValue.value !== undefined && + Object.values(ninjaMappingsArray) + .map((item) => item.ninjaId) + .includes(mappingValue.value) === false + ) { + setNinjaMappingsArray([ + ...ninjaMappingsArray, + { + Tenant: listBackendNinjaOrgsResult.data?.Tenants.find( + (tenant) => tenant.customerId === mappingArray, + ), + ninjaName: mappingValue.label, + ninjaId: mappingValue.value, + }, + ]) + } + }} className={`my-4 circular-button`} title={'+'} > From ca8fc7fe7e3050f5a3a4556c1bd7fc1fda8ad986 Mon Sep 17 00:00:00 2001 From: Chris Hamm <101881895+PremierOneData@users.noreply.github.com> Date: Mon, 13 May 2024 14:51:56 -0500 Subject: [PATCH 77/92] Update MFAReport.jsx MFARegistration can return null which isn't captured within "MFARegistration eq false"; Instead proposing use of "MFARegistration ne true" to filter accounts without MFA registration. --- src/views/identity/reports/MFAReport.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/views/identity/reports/MFAReport.jsx b/src/views/identity/reports/MFAReport.jsx index 70ece62c2b4e..4f1d80936fa2 100644 --- a/src/views/identity/reports/MFAReport.jsx +++ b/src/views/identity/reports/MFAReport.jsx @@ -139,11 +139,15 @@ const MFAList = () => { { filterName: 'Enabled, licensed non-guest users missing MFA', filter: - 'Complex: UPN notlike #EXT#; IsLicensed eq true; accountEnabled eq true; MFARegistration eq false', + 'Complex: UPN notlike #EXT#; IsLicensed eq true; accountEnabled eq true; MFARegistration ne true', }, { filterName: 'No MFA methods registered', - filter: 'Complex: MFARegistration eq false', + filter: 'Complex: MFARegistration ne true', + }, + { + filterName: 'MFA methods registered', + filter: 'Complex: MFARegistration eq true', }, ], columns: tenant.defaultDomainName === 'AllTenants' ? Altcolumns : columns, From 268abe57970a4a711463f8418eb78d654e1a21f9 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 13 May 2024 16:02:13 -0400 Subject: [PATCH 78/92] Extension Accordions --- .../contentcards/CippAccordionItem.jsx | 49 ++ .../SettingsExtensionMappings.jsx | 773 +++++++++--------- .../cipp/app-settings/SettingsExtensions.jsx | 115 +-- 3 files changed, 491 insertions(+), 446 deletions(-) create mode 100644 src/components/contentcards/CippAccordionItem.jsx diff --git a/src/components/contentcards/CippAccordionItem.jsx b/src/components/contentcards/CippAccordionItem.jsx new file mode 100644 index 000000000000..98090b58c0c7 --- /dev/null +++ b/src/components/contentcards/CippAccordionItem.jsx @@ -0,0 +1,49 @@ +import React from 'react' +import { + CAccordionBody, + CAccordionHeader, + CAccordionItem, + CCard, + CCardBody, + CCardFooter, + CCardHeader, + CCardTitle, +} from '@coreui/react' +import Skeleton from 'react-loading-skeleton' +import PropTypes from 'prop-types' + +export default function CippAccordionItem({ + title, + titleType = 'normal', + CardButton, + children, + isFetching, +}) { + return ( + + {title} + + + + + {titleType === 'big' ?

    {title}

    : title} +
    +
    + + {isFetching && } + {children} + + {CardButton} +
    +
    +
    + ) +} + +CippAccordionItem.propTypes = { + title: PropTypes.string.isRequired, + titleType: PropTypes.string, + CardButton: PropTypes.element.isRequired, + children: PropTypes.element.isRequired, + isFetching: PropTypes.bool.isRequired, +} diff --git a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx index f2deb9d187be..de3246422499 100644 --- a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx +++ b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx @@ -1,12 +1,22 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js' -import { CButton, CCallout, CCardText, CCol, CForm, CRow, CSpinner, CTooltip } from '@coreui/react' +import { + CAccordion, + CButton, + CCallout, + CCardText, + CCol, + CForm, + CRow, + CSpinner, + CTooltip, +} from '@coreui/react' import { Form } from 'react-final-form' import { RFFSelectSearch } from 'src/components/forms/index.js' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import React, { useEffect } from 'react' import { CippCallout } from 'src/components/layout/index.js' -import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import CippAccordionItem from 'src/components/contentcards/CippAccordionItem' import { CippTable } from 'src/components/tables' import { CellTip } from 'src/components/tables/CellGenericFormat' @@ -238,400 +248,385 @@ export function SettingsExtensionMappings() { listNinjaOrgsBackend({ path: 'api/ExecExtensionMapping?List=NinjaOrgs' })} {listBackendNinjaFieldsResult.isUninitialized && listNinjaFieldsBackend({ path: 'api/ExecExtensionMapping?List=NinjaFields' })} - <> - - - - {extensionHaloConfigResult.isFetching && ( - - )} - Save Mappings - - onHaloAutomap()} className="me-2"> - {extensionNinjaOrgsAutomapResult.isFetching && ( - - )} - Automap HaloPSA Clients - - - } - > - {listBackendHaloResult.isFetching && listBackendHaloResult.isUninitialized ? ( - - ) : ( - { - return ( - - - Use the table below to map your client to the correct PSA client. - { - //load all the existing mappings and show them first in a table. - listBackendHaloResult.isSuccess && ( - - ) - } - - - { - return !Object.keys(listBackendHaloResult.data?.Mappings).includes( - tenant.customerId, - ) - }).map((tenant) => ({ - name: tenant.displayName, - value: tenant.customerId, - }))} - onChange={(e) => { - setMappingArray(e.value) - }} - isLoading={listBackendHaloResult.isFetching} - /> - - - - - - { - return !Object.values(listBackendHaloResult.data?.Mappings) - .map((value) => { - return value.value - }) - .includes(client.value) - }).map((client) => ({ - name: client.name, - value: client.value, - }))} - onChange={(e) => setMappingValue(e)} - placeholder="Select a HaloPSA Client" - isLoading={listBackendHaloResult.isFetching} - /> - - { - if ( - mappingValue.value !== undefined && - Object.values(haloMappingsArray) - .map((item) => item.haloId) - .includes(mappingValue.value) === false - ) { - //set the new mapping in the array - setHaloMappingsArray([ - ...haloMappingsArray, - { - Tenant: listBackendHaloResult.data?.Tenants.find( - (tenant) => tenant.customerId === mappingArray, - ), - haloName: mappingValue.label, - haloId: mappingValue.value, - }, - ]) - } + + + + {extensionHaloConfigResult.isFetching && ( + + )} + Save Mappings + + onHaloAutomap()} className="me-2"> + {extensionNinjaOrgsAutomapResult.isFetching && ( + + )} + Automap HaloPSA Clients + + + } + > + {listBackendHaloResult.isFetching && listBackendHaloResult.isUninitialized ? ( + + ) : ( + { + return ( + + + Use the table below to map your client to the correct PSA client. + { + //load all the existing mappings and show them first in a table. + listBackendHaloResult.isSuccess && ( + + ) + } + + + { + return !Object.keys(listBackendHaloResult.data?.Mappings).includes( + tenant.customerId, + ) + }).map((tenant) => ({ + name: tenant.displayName, + value: tenant.customerId, + }))} + onChange={(e) => { + setMappingArray(e.value) }} - className={`my-4 circular-button`} - title={'+'} - > - - - - - - {HaloAutoMap && ( - - Automapping has been executed. Remember to check the changes and save - them. - - )} - {(extensionHaloConfigResult.isSuccess || - extensionHaloConfigResult.isError) && - !extensionHaloConfigResult.isFetching && ( - - {extensionHaloConfigResult.isSuccess - ? extensionHaloConfigResult.data.Results - : 'Error'} - - )} - - - - After editing the mappings you must click Save Mappings for the changes to - take effect. The table will be saved exactly as presented. - - - ) - }} - /> - )} - - - - {' '} - - - {extensionNinjaOrgsConfigResult.isFetching && ( - - )} - Set Mappings - - onNinjaOrgsAutomap()} className="me-2"> - {extensionNinjaOrgsAutomapResult.isFetching && ( - - )} - Automap NinjaOne Organizations - - - } - > - {listBackendNinjaOrgsResult.isFetching && listBackendNinjaOrgsResult.isUninitialized ? ( - - ) : ( - { - return ( - - - Use the table below to map your client to the correct NinjaOne Organization. - { - //load all the existing mappings and show them first in a table. - listBackendNinjaOrgsResult.isSuccess && ( - - ) - } - - - { - return !Object.keys( - listBackendNinjaOrgsResult.data?.Mappings, - ).includes(tenant.customerId) - }).map((tenant) => ({ - name: tenant.displayName, - value: tenant.customerId, - }))} - onChange={(e) => { - setMappingArray(e.value) - }} - isLoading={listBackendNinjaOrgsResult.isFetching} - /> - - - - - - { - return !Object.values(listBackendNinjaOrgsResult.data?.Mappings) - .map((value) => { - return value.value - }) - .includes(client.value.toString()) - }, - ).map((client) => ({ - name: client.name, - value: client.value, - }))} - onChange={(e) => setMappingValue(e)} - placeholder="Select a NinjaOne Organization" - isLoading={listBackendNinjaOrgsResult.isFetching} - /> - - { + isLoading={listBackendHaloResult.isFetching} + /> + + + + + + { + return !Object.values(listBackendHaloResult.data?.Mappings) + .map((value) => { + return value.value + }) + .includes(client.value) + }).map((client) => ({ + name: client.name, + value: client.value, + }))} + onChange={(e) => setMappingValue(e)} + placeholder="Select a HaloPSA Client" + isLoading={listBackendHaloResult.isFetching} + /> + + { + if ( + mappingValue.value !== undefined && + Object.values(haloMappingsArray) + .map((item) => item.haloId) + .includes(mappingValue.value) === false + ) { //set the new mapping in the array - if ( - mappingValue.value !== undefined && - Object.values(ninjaMappingsArray) - .map((item) => item.ninjaId) - .includes(mappingValue.value) === false - ) { - setNinjaMappingsArray([ - ...ninjaMappingsArray, - { - Tenant: listBackendNinjaOrgsResult.data?.Tenants.find( - (tenant) => tenant.customerId === mappingArray, - ), - ninjaName: mappingValue.label, - ninjaId: mappingValue.value, - }, - ]) - } - }} - className={`my-4 circular-button`} - title={'+'} + setHaloMappingsArray([ + ...haloMappingsArray, + { + Tenant: listBackendHaloResult.data?.Tenants.find( + (tenant) => tenant.customerId === mappingArray, + ), + haloName: mappingValue.label, + haloId: mappingValue.value, + }, + ]) + } + }} + className={`my-4 circular-button`} + title={'+'} + > + + +
    + + + {HaloAutoMap && ( + + Automapping has been executed. Remember to check the changes and save + them. + + )} + {(extensionHaloConfigResult.isSuccess || extensionHaloConfigResult.isError) && + !extensionHaloConfigResult.isFetching && ( + - - - - - - {(extensionNinjaOrgsAutomapResult.isSuccess || - extensionNinjaOrgsAutomapResult.isError) && - !extensionNinjaOrgsAutomapResult.isFetching && ( - - {extensionNinjaOrgsAutomapResult.isSuccess - ? extensionNinjaOrgsAutomapResult.data.Results - : 'Error'} - - )} - {(extensionNinjaOrgsConfigResult.isSuccess || - extensionNinjaOrgsConfigResult.isError) && - !extensionNinjaOrgsConfigResult.isFetching && ( - - {extensionNinjaOrgsConfigResult.isSuccess - ? extensionNinjaOrgsConfigResult.data.Results - : 'Error'} - - )} - - - - After editing the mappings you must click Save Mappings for the changes to - take effect. The table will be saved exactly as presented. - -
    - ) - }} - /> - )} - - - - - {extensionNinjaFieldsConfigResult.isFetching && ( + {extensionHaloConfigResult.isSuccess + ? extensionHaloConfigResult.data.Results + : 'Error'} + + )} + + + + After editing the mappings you must click Save Mappings for the changes to + take effect. The table will be saved exactly as presented. + + + ) + }} + /> + )} + + + + {extensionNinjaOrgsConfigResult.isFetching && ( )} Set Mappings - } - > - {listBackendNinjaFieldsResult.isFetching ? ( - - ) : ( - { - return ( - - -
    Organization Global Custom Field Mapping
    -

    - Use the table below to map your Organization Field to the correct NinjaOne - Field -

    - {listBackendNinjaFieldsResult.isSuccess && - listBackendNinjaFieldsResult.data.CIPPOrgFields.map((CIPPOrgFields) => ( - item.type === CIPPOrgFields.Type || item.type === 'unset', - )} - placeholder="Select a Field" - /> - ))} -
    - -
    Device Custom Field Mapping
    -

    - Use the table below to map your Device field to the correct NinjaOne - WYSIWYG Field -

    - {listBackendNinjaFieldsResult.isSuccess && - listBackendNinjaFieldsResult.data.CIPPNodeFields.map((CIPPNodeFields) => ( - - item.type === CIPPNodeFields.Type || item.type === 'unset', - )} - placeholder="Select a Field" - /> - ))} -
    - - {(extensionNinjaFieldsConfigResult.isSuccess || - extensionNinjaFieldsConfigResult.isError) && - !extensionNinjaFieldsConfigResult.isFetching && ( - - {extensionNinjaFieldsConfigResult.isSuccess - ? extensionNinjaFieldsConfigResult.data.Results - : 'Error'} - - )} - -
    - ) - }} - /> - )} - - - + onNinjaOrgsAutomap()} className="me-2"> + {extensionNinjaOrgsAutomapResult.isFetching && ( + + )} + Automap NinjaOne Organizations + + + } + > + {listBackendNinjaOrgsResult.isFetching && listBackendNinjaOrgsResult.isUninitialized ? ( + + ) : ( + { + return ( + + + Use the table below to map your client to the correct NinjaOne Organization. + { + //load all the existing mappings and show them first in a table. + listBackendNinjaOrgsResult.isSuccess && ( + + ) + } + + + { + return !Object.keys( + listBackendNinjaOrgsResult.data?.Mappings, + ).includes(tenant.customerId) + }).map((tenant) => ({ + name: tenant.displayName, + value: tenant.customerId, + }))} + onChange={(e) => { + setMappingArray(e.value) + }} + isLoading={listBackendNinjaOrgsResult.isFetching} + /> + + + + + + { + return !Object.values(listBackendNinjaOrgsResult.data?.Mappings) + .map((value) => { + return value.value + }) + .includes(client.value.toString()) + }).map((client) => ({ + name: client.name, + value: client.value, + }))} + onChange={(e) => setMappingValue(e)} + placeholder="Select a NinjaOne Organization" + isLoading={listBackendNinjaOrgsResult.isFetching} + /> + + { + //set the new mapping in the array + if ( + mappingValue.value !== undefined && + Object.values(ninjaMappingsArray) + .map((item) => item.ninjaId) + .includes(mappingValue.value) === false + ) { + setNinjaMappingsArray([ + ...ninjaMappingsArray, + { + Tenant: listBackendNinjaOrgsResult.data?.Tenants.find( + (tenant) => tenant.customerId === mappingArray, + ), + ninjaName: mappingValue.label, + ninjaId: mappingValue.value, + }, + ]) + } + }} + className={`my-4 circular-button`} + title={'+'} + > + + + + + + {(extensionNinjaOrgsAutomapResult.isSuccess || + extensionNinjaOrgsAutomapResult.isError) && + !extensionNinjaOrgsAutomapResult.isFetching && ( + + {extensionNinjaOrgsAutomapResult.isSuccess + ? extensionNinjaOrgsAutomapResult.data.Results + : 'Error'} + + )} + {(extensionNinjaOrgsConfigResult.isSuccess || + extensionNinjaOrgsConfigResult.isError) && + !extensionNinjaOrgsConfigResult.isFetching && ( + + {extensionNinjaOrgsConfigResult.isSuccess + ? extensionNinjaOrgsConfigResult.data.Results + : 'Error'} + + )} + + + + After editing the mappings you must click Save Mappings for the changes to + take effect. The table will be saved exactly as presented. + + + ) + }} + /> + )} +
    + + {extensionNinjaFieldsConfigResult.isFetching && ( + + )} + Set Mappings + + } + > + {listBackendNinjaFieldsResult.isFetching ? ( + + ) : ( + { + return ( + + +
    Organization Global Custom Field Mapping
    +

    + Use the table below to map your Organization Field to the correct NinjaOne + Field +

    + {listBackendNinjaFieldsResult.isSuccess && + listBackendNinjaFieldsResult.data.CIPPOrgFields.map((CIPPOrgFields) => ( + item.type === CIPPOrgFields.Type || item.type === 'unset', + )} + placeholder="Select a Field" + /> + ))} +
    + +
    Device Custom Field Mapping
    +

    + Use the table below to map your Device field to the correct NinjaOne WYSIWYG + Field +

    + {listBackendNinjaFieldsResult.isSuccess && + listBackendNinjaFieldsResult.data.CIPPNodeFields.map((CIPPNodeFields) => ( + item.type === CIPPNodeFields.Type || item.type === 'unset', + )} + placeholder="Select a Field" + /> + ))} +
    + + {(extensionNinjaFieldsConfigResult.isSuccess || + extensionNinjaFieldsConfigResult.isError) && + !extensionNinjaFieldsConfigResult.isFetching && ( + + {extensionNinjaFieldsConfigResult.isSuccess + ? extensionNinjaFieldsConfigResult.data.Results + : 'Error'} + + )} + +
    + ) + }} + /> + )} +
    + ) } diff --git a/src/views/cipp/app-settings/SettingsExtensions.jsx b/src/views/cipp/app-settings/SettingsExtensions.jsx index fc728407ded3..20ebbcee9725 100644 --- a/src/views/cipp/app-settings/SettingsExtensions.jsx +++ b/src/views/cipp/app-settings/SettingsExtensions.jsx @@ -1,6 +1,7 @@ import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js' import React, { useRef } from 'react' import { + CAccordion, CAlert, CButton, CCallout, @@ -21,6 +22,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import { CippCallout } from 'src/components/layout/index.js' import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import CippAccordionItem from 'src/components/contentcards/CippAccordionItem' /** * Executes various operations related to settings and extensions. @@ -105,65 +107,64 @@ export function SettingsExtensions() { {extensionConfigResult.data.Results} )} - + {Extensions.map((integration, idx) => ( - - -

    {integration.helpText}

    - { - return ( - - - - {integration.SettingOptions.map( - (integrationOptions, idx) => - integrationOptions.type === 'input' && ( - - - - ), - )} - {integration.SettingOptions.map( - (integrationOptions, idx) => - integrationOptions.type === 'checkbox' && ( - - - - ), - )} - - - - - ) - }} - /> -
    -
    + +

    {integration.helpText}

    + { + return ( + + + + {integration.SettingOptions.map( + (integrationOptions, idx) => + integrationOptions.type === 'input' && ( + + + + ), + )} + {integration.SettingOptions.map( + (integrationOptions, idx) => + integrationOptions.type === 'checkbox' && ( + + + + ), + )} + + + + + ) + }} + /> +
    ))} -
    +
    ) From 8f8b37691aff7ae722ba4139d40b26d534284c86 Mon Sep 17 00:00:00 2001 From: Chris Hamm <101881895+PremierOneData@users.noreply.github.com> Date: Mon, 13 May 2024 15:06:58 -0500 Subject: [PATCH 79/92] Update ConnectorList.jsx Added a variety of filters for Transport Connectors --- src/views/email-exchange/connectors/ConnectorList.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/views/email-exchange/connectors/ConnectorList.jsx b/src/views/email-exchange/connectors/ConnectorList.jsx index 990e1d555199..5abba8ca1167 100644 --- a/src/views/email-exchange/connectors/ConnectorList.jsx +++ b/src/views/email-exchange/connectors/ConnectorList.jsx @@ -151,6 +151,14 @@ const ConnectorList = () => { } tenantSelector={true} datatable={{ + filterlist: [ + { filterName: 'Enabled connectors', filter: 'Complex: Enabled eq true' }, + { filterName: 'Disabled connectors', filter: 'Complex: Enabled eq false' }, + { filterName: 'Inbound connectors', filter: 'Complex: cippconnectortype eq inbound' }, + { filterName: 'Outbound connectors', filter: 'Complex: cippconnectortype eq outbound' }, + { filterName: 'Transport rule connectors', filter: 'Complex: IsTransportRuleScoped eq true' }, + { filterName: 'Non-transport rule connectors', filter: 'Complex: IsTransportRuleScoped eq false' }, + ], reportName: `${tenant?.defaultDomainName}-connectors-list`, path: '/api/ListExchangeConnectors', params: { TenantFilter: tenant?.defaultDomainName }, From 1ef999ff3bfc472c61c6ed7cea9f0b53cfc3550e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 May 2024 22:08:16 +0200 Subject: [PATCH 80/92] fix linting issue --- src/views/email-exchange/administration/QuarantineList.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/views/email-exchange/administration/QuarantineList.jsx b/src/views/email-exchange/administration/QuarantineList.jsx index 35c66dacc21f..7453af66b1a7 100644 --- a/src/views/email-exchange/administration/QuarantineList.jsx +++ b/src/views/email-exchange/administration/QuarantineList.jsx @@ -161,9 +161,10 @@ const QuarantineList = () => { color: 'info', modal: true, modalUrl: `/api/ExecQuarantineManagement?TenantFilter=${tenant.defaultDomainName}&ID=!Identity&Type=Release&AllowSender=true`, - modalMessage: 'Are you sure you want to release these messages, and add the senders to the whitelist?', + modalMessage: + 'Are you sure you want to release these messages, and add the senders to the whitelist?', }, - ] + ], }, params: { TenantFilter: tenant?.defaultDomainName }, }} From ef95912d938f3ec254291beef99eaf4324551770 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 May 2024 11:16:01 -0400 Subject: [PATCH 81/92] Add additional template types Fixes #2414 --- src/views/endpoint/intune/MEMAddPolicyTemplate.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/endpoint/intune/MEMAddPolicyTemplate.jsx b/src/views/endpoint/intune/MEMAddPolicyTemplate.jsx index 7d8e752d6a72..a6774de654dd 100644 --- a/src/views/endpoint/intune/MEMAddPolicyTemplate.jsx +++ b/src/views/endpoint/intune/MEMAddPolicyTemplate.jsx @@ -58,8 +58,10 @@ const MEMAddPolicyTemplate = () => { label="Select Policy Type" placeholder="Select a template type" values={[ + { label: 'App Protection Policy', value: 'AppProtection' }, { label: 'Administrative Template', value: 'Admin' }, { label: 'Settings Catalog', value: 'Catalog' }, + { label: 'Device Compliance Policy', value: 'deviceCompliancePolicies' }, { label: 'Custom Configuration', value: 'Device' }, ]} validate={required} From 5029187dd415db281b2d19330f1573f48b073e6c Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 May 2024 11:33:15 -0400 Subject: [PATCH 82/92] fix linting issue --- src/views/email-exchange/connectors/ConnectorList.jsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/views/email-exchange/connectors/ConnectorList.jsx b/src/views/email-exchange/connectors/ConnectorList.jsx index 5abba8ca1167..c18d5eeb0004 100644 --- a/src/views/email-exchange/connectors/ConnectorList.jsx +++ b/src/views/email-exchange/connectors/ConnectorList.jsx @@ -156,8 +156,14 @@ const ConnectorList = () => { { filterName: 'Disabled connectors', filter: 'Complex: Enabled eq false' }, { filterName: 'Inbound connectors', filter: 'Complex: cippconnectortype eq inbound' }, { filterName: 'Outbound connectors', filter: 'Complex: cippconnectortype eq outbound' }, - { filterName: 'Transport rule connectors', filter: 'Complex: IsTransportRuleScoped eq true' }, - { filterName: 'Non-transport rule connectors', filter: 'Complex: IsTransportRuleScoped eq false' }, + { + filterName: 'Transport rule connectors', + filter: 'Complex: IsTransportRuleScoped eq true', + }, + { + filterName: 'Non-transport rule connectors', + filter: 'Complex: IsTransportRuleScoped eq false', + }, ], reportName: `${tenant?.defaultDomainName}-connectors-list`, path: '/api/ListExchangeConnectors', From e2bf01ee88aecf8090e27455d623b2dec73b3536 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 May 2024 14:10:33 -0400 Subject: [PATCH 83/92] On prem sync warnings --- src/views/identity/administration/EditUser.jsx | 8 +++++++- .../administration/OffboardingWizard.jsx | 18 ++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/views/identity/administration/EditUser.jsx b/src/views/identity/administration/EditUser.jsx index 3cfc21641997..2f90bedb20e8 100644 --- a/src/views/identity/administration/EditUser.jsx +++ b/src/views/identity/administration/EditUser.jsx @@ -167,6 +167,12 @@ const EditUser = () => { link for more information. )} + {user?.onPremisesSyncEnabled === true && ( + + Warning! This user Active Directory sync enabled. Edits should be made from a Domain + Controller. + + )} {postResults.isSuccess && ( {postResults.data?.Results} )} @@ -180,7 +186,7 @@ const EditUser = () => { )} - + {userIsFetching && } diff --git a/src/views/identity/administration/OffboardingWizard.jsx b/src/views/identity/administration/OffboardingWizard.jsx index e7ba79912958..b5b344969c7a 100644 --- a/src/views/identity/administration/OffboardingWizard.jsx +++ b/src/views/identity/administration/OffboardingWizard.jsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import { CCallout, CCol, CListGroup, CListGroupItem, CRow, CSpinner } from '@coreui/react' +import { CCallout, CCol, CListGroup, CListGroupItem, CRow, CSpinner, CTooltip } from '@coreui/react' import { Field, FormSpy } from 'react-final-form' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faExclamationTriangle, faTimes, faCheck } from '@fortawesome/free-solid-svg-icons' @@ -296,7 +296,21 @@ const OffboardingWizard = () => { className="d-flex justify-content-between align-items-center" >
    Selected User:
    - {user.value} + + {users.find((x) => x.userPrincipalName === user.value) + .onPremisesSyncEnabled === true ? ( + + + + ) : ( + '' + )} + {user.value} + ))} From 7313277f51fbe2403a6cd0e2a80dbdbb4cda6873 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 May 2024 21:30:30 +0200 Subject: [PATCH 84/92] updated audit log template --- src/data/AuditLogTemplates.json | 36 +++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index 723b7c39dd34..d4a274e4f754 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -169,12 +169,44 @@ { "value": "Add service principal.", "name": "A service principal has been created", - "template": [] + "template": { + "preset": { + "value": "Add service principal.", + "label": "A service principal has been created" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals to" }, + "Input": { + "value": "Add service principal.", + "label": "Add service principal." + } + } + ] + } }, { "value": "Remove service principal.", "name": "A service principal has been removed", - "template": [] + "template": { + "preset": { + "value": "Remove service principal.", + "label": "A service principal has been removed" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals to" }, + "Input": { + "value": "Remove service principal.", + "label": "Remove service principal." + } + } + ] + } }, { "value": "badRepIP", From f0e0bfeb10a9dc82e895c10c92711f5122569090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 14 May 2024 21:34:41 +0200 Subject: [PATCH 85/92] Add filter for non-Microsoft service principals in ListEnterpriseApps.jsx --- src/views/tenant/administration/ListEnterpriseApps.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/views/tenant/administration/ListEnterpriseApps.jsx b/src/views/tenant/administration/ListEnterpriseApps.jsx index 5b2385a6c0f1..bf49da8c0b67 100644 --- a/src/views/tenant/administration/ListEnterpriseApps.jsx +++ b/src/views/tenant/administration/ListEnterpriseApps.jsx @@ -90,6 +90,11 @@ const EnterpriseApplications = () => { filter: "Graph: tags/any(t:t eq 'WindowsAzureActiveDirectoryGalleryApplicationPrimaryV1')", }, + { + filterName: 'All non-Microsoft Enterprise Apps', + filter: + 'Complex: appOwnerOrganizationId notlike f8cdef31-a31e-4b4a-93e4-5f571e91255a', + }, ], tableProps: { selectableRows: true, From 7f546cad3fa874401f8ef040845a88c098209365 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 May 2024 19:05:28 -0400 Subject: [PATCH 86/92] Tenant Onboarding v2 --- src/_nav.jsx | 2 +- src/components/tables/CippTable.jsx | 4 +- src/importsMap.jsx | 1 + src/routes.json | 6 + .../administration/TenantOnboarding.jsx | 153 ++++++++++++++ .../administration/TenantOnboardingWizard.jsx | 184 +---------------- .../onboarding/RelationshipOnboarding.jsx | 195 ++++++++++++++++++ 7 files changed, 370 insertions(+), 175 deletions(-) create mode 100644 src/views/tenant/administration/TenantOnboarding.jsx create mode 100644 src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx diff --git a/src/_nav.jsx b/src/_nav.jsx index 2f99dffd0953..902a8390b79f 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -150,7 +150,7 @@ const _nav = [ { component: CNavItem, name: 'Tenant Onboarding', - to: '/tenant/administration/tenant-onboarding-wizard', + to: '/tenant/administration/tenant-onboarding', }, { component: CNavItem, diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx index c977c700cc87..f3ea486ee243 100644 --- a/src/components/tables/CippTable.jsx +++ b/src/components/tables/CippTable.jsx @@ -125,6 +125,7 @@ export default function CippTable({ filterlist, showFilter = true, endpointName, + defaultSortAsc = true, tableProps: { keyField = 'id', theme = 'cyberdrain', @@ -989,7 +990,7 @@ export default function CippTable({ expandableRowsComponent={expandableRowsComponent} highlightOnHover={highlightOnHover} expandOnRowClicked={expandOnRowClicked} - defaultSortAsc + defaultSortAsc={defaultSortAsc} defaultSortFieldId={1} sortFunction={customSort} paginationPerPage={tablePageSize} @@ -1050,6 +1051,7 @@ export const CippTablePropTypes = { disableCSVExport: PropTypes.bool, error: PropTypes.object, filterlist: PropTypes.arrayOf(PropTypes.object), + defaultSortAsc: PropTypes.bool, } CippTable.propTypes = CippTablePropTypes diff --git a/src/importsMap.jsx b/src/importsMap.jsx index 7b7589049b42..fd44014ae9c7 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -140,6 +140,7 @@ import React from 'react' "/tenant/administration/gdap-status": React.lazy(() => import('./views/tenant/administration/ListGDAPQueue')), "/tenant/standards/list-standards": React.lazy(() => import('./views/tenant/standards/ListStandards')), "/tenant/administration/tenant-offboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOffboardingWizard')), + "/tenant/administration/tenant-onboarding": React.lazy(() => import('./views/tenant/administration/TenantOnboarding')), "/tenant/administration/tenant-onboarding-wizard": React.lazy(() => import('./views/tenant/administration/TenantOnboardingWizard')), } export default importsMap \ No newline at end of file diff --git a/src/routes.json b/src/routes.json index e1d382459781..e681555e0346 100644 --- a/src/routes.json +++ b/src/routes.json @@ -954,6 +954,12 @@ "component": "views/tenant/administration/TenantOffboardingWizard", "allowedRoles": ["admin"] }, + { + "path": "/tenant/administration/tenant-onboarding", + "name": "Tenant Onboarding", + "component": "views/tenant/administration/TenantOnboarding", + "allowedRoles": ["admin"] + }, { "path": "/tenant/administration/tenant-onboarding-wizard", "name": "Tenant Onboarding", diff --git a/src/views/tenant/administration/TenantOnboarding.jsx b/src/views/tenant/administration/TenantOnboarding.jsx new file mode 100644 index 000000000000..94afd7437938 --- /dev/null +++ b/src/views/tenant/administration/TenantOnboarding.jsx @@ -0,0 +1,153 @@ +import { CBadge, CTooltip } from '@coreui/react' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import React from 'react' +import { TitleButton } from 'src/components/buttons' +import { CippPageList } from 'src/components/layout' +import { CellBadge, cellDateFormatter } from 'src/components/tables' +import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' + +const TenantOnboarding = () => { + const titleButton = ( + + ) + function ucfirst(str) { + return str.charAt(0).toUpperCase() + str.slice(1) + } + function getBadgeColor(status) { + switch (status.toLowerCase()) { + case 'queued': + return 'info' + case 'failed': + return 'danger' + case 'succeeded': + return 'success' + case 'running': + return 'primary' + } + } + function getLatestStep(steps) { + var activeSteps = steps?.filter((step) => step.Status !== 'pending') + var currentStep = activeSteps[activeSteps.length - 1] + var color = 'info' + var icon = 'me-2 info-circle' + var spin = false + switch (currentStep?.Status) { + case 'succeeded': + color = 'me-2 text-success' + icon = 'check-circle' + break + case 'failed': + color = 'me-2 text-danger' + icon = 'times-circle' + break + case 'running': + color = 'me-2 text-primary' + icon = 'sync' + spin = true + break + } + return ( + +
    + + {currentStep?.Title} +
    +
    + ) + } + const columns = [ + { + name: 'Last Update', + selector: (row) => row.Timestamp, + sortable: true, + exportSelector: 'Timestamp', + cell: cellDateFormatter({ format: 'short' }), + }, + { + name: 'Tenant', + selector: (row) => row?.Relationship?.customer?.displayName, + sortable: true, + cell: cellGenericFormatter(), + exportSelector: 'Relationship/customer/displayName', + }, + { + name: 'Status', + selector: (row) => row?.Status, + sortable: true, + exportSelector: 'Status', + cell: (row) => CellBadge({ label: ucfirst(row?.Status), color: getBadgeColor(row?.Status) }), + }, + { + name: 'Onboarding Step', + selector: (row) => row?.OnboardingSteps, + cell: (row) => getLatestStep(row?.OnboardingSteps), + }, + { + name: 'Logs', + selector: (row) => row?.Logs, + sortable: false, + cell: cellGenericFormatter(), + }, + ] + return ( +
    + +
    + ) +} + +export default TenantOnboarding diff --git a/src/views/tenant/administration/TenantOnboardingWizard.jsx b/src/views/tenant/administration/TenantOnboardingWizard.jsx index 122765dff6c3..874510c3517e 100644 --- a/src/views/tenant/administration/TenantOnboardingWizard.jsx +++ b/src/views/tenant/administration/TenantOnboardingWizard.jsx @@ -1,32 +1,16 @@ -import React, { useState, useRef, useEffect } from 'react' -import { - CAccordion, - CAccordionBody, - CAccordionHeader, - CAccordionItem, - CButton, - CCallout, - CCol, - CRow, - CSpinner, -} from '@coreui/react' +import React, { useRef, useEffect } from 'react' +import { CAccordion, CCallout, CCol, CRow } from '@coreui/react' import { Field, FormSpy } from 'react-final-form' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faExclamationTriangle, faTimes, faCheck } from '@fortawesome/free-solid-svg-icons' import { useSelector } from 'react-redux' import { CippWizard } from 'src/components/layout' import PropTypes from 'prop-types' -import { RFFCFormCheck, RFFCFormInput, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms' -import { CippCodeBlock, TenantSelector } from 'src/components/utilities' +import { RFFCFormSwitch } from 'src/components/forms' import { useLazyGenericPostRequestQuery } from 'src/store/api/app' -import { - CellDate, - WizardTableField, - cellDateFormatter, - cellNullTextFormatter, -} from 'src/components/tables' -import ReactTimeAgo from 'react-time-ago' -import { TableModalButton, TitleButton } from 'src/components/buttons' +import { WizardTableField, cellDateFormatter, cellNullTextFormatter } from 'src/components/tables' +import { TitleButton } from 'src/components/buttons' +import RelationshipOnboarding from 'src/views/tenant/administration/onboarding/RelationshipOnboarding' const Error = ({ name }) => ( { - const [relationshipReady, setRelationshipReady] = useState(false) - const [refreshGuid, setRefreshGuid] = useState(false) - const [getOnboardingStatus, onboardingStatus] = useLazyGenericPostRequestQuery() - var headerIcon = relationshipReady ? 'check-circle' : 'question-circle' - - useInterval( - async () => { - if (onboardingStatus.data?.Status == 'running' || onboardingStatus.data?.Status == 'queued') { - getOnboardingStatus({ - path: '/api/ExecOnboardTenant', - values: { id: relationship.id }, - }) - } - }, - 5000, - onboardingStatus.data, - ) - - return ( - - - {onboardingStatus?.data?.Status == 'running' ? ( - - ) : ( - - )} - Onboarding Relationship: {} - {relationship.displayName} - - - - {(relationship?.customer?.displayName || - onboardingStatus?.data?.Relationship?.customer?.displayName) && ( - -

    Customer

    - {onboardingStatus?.data?.Relationship?.customer?.displayName - ? onboardingStatus?.data?.Relationship?.customer?.displayName - : relationship.customer.displayName} -
    - )} - {onboardingStatus?.data?.Timestamp && ( - -

    Last Updated

    - -
    - )} - -

    Relationship Status

    - {relationship.status} -
    - -

    Creation Date

    - -
    - {relationship.status == 'approvalPending' && - onboardingStatus?.data?.Relationship?.status != 'active' && ( - -

    Invite URL

    - -
    - )} -
    - {onboardingStatus.isUninitialized && - getOnboardingStatus({ - path: '/api/ExecOnboardTenant', - values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups }, - })} - {onboardingStatus.isSuccess && ( - <> - {onboardingStatus.data?.Status != 'queued' && ( - - getOnboardingStatus({ - path: '/api/ExecOnboardTenant?Retry=True', - values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups }, - }) - } - className="mb-3 me-2" - > - Retry - - )} - {onboardingStatus.data?.Logs && ( - - )} -
    - {onboardingStatus.data?.OnboardingSteps?.map((step, idx) => ( - - - {step.Status == 'running' ? ( - - ) : ( - - )}{' '} - {step.Title} - - - {step.Message} - - - ))} - - )} -
    -
    - ) -} -RelationshipOnboarding.propTypes = { - relationship: PropTypes.object.isRequired, - gdapRoles: PropTypes.array, - autoMapRoles: PropTypes.bool, - addMissingGroups: PropTypes.bool, -} - const TenantOnboardingWizard = () => { const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName) const currentSettings = useSelector((state) => state.app) @@ -350,6 +183,11 @@ const TenantOnboardingWizard = () => {
    Tenant Onboarding Options

    +
    Optional Settings
    +

    + Use these options for relationships created outside of the CIPP Invite Wizard or if the + SAM user is missing required GDAP groups from the Partner Tenant. +

    diff --git a/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx b/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx new file mode 100644 index 000000000000..3f5c93f4ab12 --- /dev/null +++ b/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx @@ -0,0 +1,195 @@ +import React, { useState, useRef, useEffect } from 'react' +import { + CAccordionBody, + CAccordionHeader, + CAccordionItem, + CButton, + CCallout, + CCol, + CRow, + CSpinner, +} from '@coreui/react' +import { Field } from 'react-final-form' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faExclamationTriangle, faTimes, faCheck } from '@fortawesome/free-solid-svg-icons' +import PropTypes from 'prop-types' +import { CippCodeBlock, TenantSelector } from 'src/components/utilities' +import { useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { CellDate } from 'src/components/tables' +import ReactTimeAgo from 'react-time-ago' +import { TableModalButton, TitleButton } from 'src/components/buttons' + +function useInterval(callback, delay, state) { + const savedCallback = useRef() + + // Remember the latest callback. + useEffect(() => { + savedCallback.current = callback + }) + + // Set up the interval. + useEffect(() => { + function tick() { + savedCallback.current() + } + + if (delay !== null) { + let id = setInterval(tick, delay) + return () => clearInterval(id) + } + }, [delay, state]) +} + +const RelationshipOnboarding = ({ relationship, gdapRoles, autoMapRoles, addMissingGroups }) => { + const [relationshipReady, setRelationshipReady] = useState(false) + const [refreshGuid, setRefreshGuid] = useState(false) + const [getOnboardingStatus, onboardingStatus] = useLazyGenericPostRequestQuery() + var headerIcon = relationshipReady ? 'check-circle' : 'question-circle' + + useInterval( + async () => { + if (onboardingStatus.data?.Status == 'running' || onboardingStatus.data?.Status == 'queued') { + getOnboardingStatus({ + path: `/api/ExecOnboardTenant`, + values: { id: relationship.id }, + }) + } + }, + 5000, + onboardingStatus.data, + ) + + return ( + + + {onboardingStatus?.data?.Status == 'running' ? ( + + ) : ( + + )} + Onboarding Relationship: {} + {relationship.displayName} + + + + {(relationship?.customer?.displayName || + onboardingStatus?.data?.Relationship?.customer?.displayName) && ( + +

    Customer

    + {onboardingStatus?.data?.Relationship?.customer?.displayName + ? onboardingStatus?.data?.Relationship?.customer?.displayName + : relationship.customer.displayName} +
    + )} + {onboardingStatus?.data?.Timestamp && ( + +

    Last Updated

    + +
    + )} + +

    Relationship Status

    + {relationship.status} +
    + +

    Creation Date

    + +
    + {relationship.status == 'approvalPending' && + onboardingStatus?.data?.Relationship?.status != 'active' && ( + +

    Invite URL

    + +
    + )} +
    + {onboardingStatus.isUninitialized && + getOnboardingStatus({ + path: '/api/ExecOnboardTenant', + values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups }, + })} + {onboardingStatus.isSuccess && ( + <> + {onboardingStatus.data?.Status != 'queued' && ( + + getOnboardingStatus({ + path: '/api/ExecOnboardTenant?Retry=True', + values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups }, + }) + } + className="mb-3 me-2" + > + Retry + + )} + {onboardingStatus.data?.Logs && ( + + )} +
    + {onboardingStatus.data?.OnboardingSteps?.map((step, idx) => ( + + + {step.Status == 'running' ? ( + + ) : ( + + )}{' '} + {step.Title} + + + {step.Message} + + + ))} + + )} +
    +
    + ) +} +RelationshipOnboarding.propTypes = { + relationship: PropTypes.object.isRequired, + gdapRoles: PropTypes.array, + autoMapRoles: PropTypes.bool, + addMissingGroups: PropTypes.bool, + statusOnly: PropTypes.bool, +} + +export default RelationshipOnboarding From c8bcc83b06eaa9d11f60f74a18ff279f868935e5 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 15 May 2024 00:45:21 -0400 Subject: [PATCH 87/92] Onboarding Standards Exclusion --- .../utilities/CippTableOffcanvas.jsx | 2 +- .../administration/TenantOnboardingWizard.jsx | 10 +++++++ .../onboarding/RelationshipOnboarding.jsx | 29 +++++++++++++++---- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/components/utilities/CippTableOffcanvas.jsx b/src/components/utilities/CippTableOffcanvas.jsx index 561d0e6839b1..236ccff04b4e 100644 --- a/src/components/utilities/CippTableOffcanvas.jsx +++ b/src/components/utilities/CippTableOffcanvas.jsx @@ -14,7 +14,7 @@ function CippTableOffcanvas({ tableProps, data = null, }) { - if (Array.isArray(data) && data !== null && data !== undefined) { + if (Array.isArray(data) && data !== null && data !== undefined && data?.length > 0) { if (!Array.isArray(data) && typeof data === 'object') { data = Object.keys(data).map((key) => { return { diff --git a/src/views/tenant/administration/TenantOnboardingWizard.jsx b/src/views/tenant/administration/TenantOnboardingWizard.jsx index 874510c3517e..ebbab2a8e178 100644 --- a/src/views/tenant/administration/TenantOnboardingWizard.jsx +++ b/src/views/tenant/administration/TenantOnboardingWizard.jsx @@ -183,6 +183,15 @@ const TenantOnboardingWizard = () => {
    Tenant Onboarding Options

    +
    Standards
    +
    Optional Settings

    Use these options for relationships created outside of the CIPP Invite Wizard or if the @@ -257,6 +266,7 @@ const TenantOnboardingWizard = () => { gdapRoles={props.values.gdapRoles} autoMapRoles={props.values.autoMapRoles} addMissingGroups={props.values.addMissingGroups} + standardsExcludeAllTenants={props.values.standardsExcludeAllTenants} key={idx} /> ))} diff --git a/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx b/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx index 3f5c93f4ab12..9147caebbf63 100644 --- a/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx +++ b/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx @@ -40,11 +40,14 @@ function useInterval(callback, delay, state) { }, [delay, state]) } -const RelationshipOnboarding = ({ relationship, gdapRoles, autoMapRoles, addMissingGroups }) => { - const [relationshipReady, setRelationshipReady] = useState(false) - const [refreshGuid, setRefreshGuid] = useState(false) +const RelationshipOnboarding = ({ + relationship, + gdapRoles, + autoMapRoles, + addMissingGroups, + standardsExcludeAllTenants, +}) => { const [getOnboardingStatus, onboardingStatus] = useLazyGenericPostRequestQuery() - var headerIcon = relationshipReady ? 'check-circle' : 'question-circle' useInterval( async () => { @@ -58,6 +61,7 @@ const RelationshipOnboarding = ({ relationship, gdapRoles, autoMapRoles, addMiss 5000, onboardingStatus.data, ) + console.log(standardsExcludeAllTenants) return ( @@ -125,7 +129,13 @@ const RelationshipOnboarding = ({ relationship, gdapRoles, autoMapRoles, addMiss {onboardingStatus.isUninitialized && getOnboardingStatus({ path: '/api/ExecOnboardTenant', - values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups }, + values: { + id: relationship.id, + gdapRoles, + autoMapRoles, + addMissingGroups, + standardsExcludeAllTenants, + }, })} {onboardingStatus.isSuccess && ( <> @@ -134,7 +144,13 @@ const RelationshipOnboarding = ({ relationship, gdapRoles, autoMapRoles, addMiss onClick={() => getOnboardingStatus({ path: '/api/ExecOnboardTenant?Retry=True', - values: { id: relationship.id, gdapRoles, autoMapRoles, addMissingGroups }, + values: { + id: relationship.id, + gdapRoles, + autoMapRoles, + addMissingGroups, + standardsExcludeAllTenants, + }, }) } className="mb-3 me-2" @@ -190,6 +206,7 @@ RelationshipOnboarding.propTypes = { autoMapRoles: PropTypes.bool, addMissingGroups: PropTypes.bool, statusOnly: PropTypes.bool, + standardsExcludeAllTenants: PropTypes.bool, } export default RelationshipOnboarding From d23081336a5030ede339889376fe899fa297ee3f Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 15 May 2024 09:29:22 -0400 Subject: [PATCH 88/92] Add standard exclusion to partner webhook --- src/views/cipp/app-settings/SettingsPartner.jsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/views/cipp/app-settings/SettingsPartner.jsx b/src/views/cipp/app-settings/SettingsPartner.jsx index 388e2a6a6e9d..b569b9c33c24 100644 --- a/src/views/cipp/app-settings/SettingsPartner.jsx +++ b/src/views/cipp/app-settings/SettingsPartner.jsx @@ -19,7 +19,7 @@ import { CSpinner, } from '@coreui/react' import { Form } from 'react-final-form' -import { RFFSelectSearch } from 'src/components/forms/index.js' +import { RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms/index.js' import React, { useEffect } from 'react' import { CippCallout } from 'src/components/layout/index.js' import { CippCodeBlock } from 'src/components/utilities' @@ -45,6 +45,7 @@ export function SettingsPartner() { const onSubmit = (values) => { const shippedValues = { EventType: values?.EventType?.map((event) => event.value), + standardsExcludeAllTenants: values?.standardsExcludeAllTenants, } submitWebhook({ path: '/api/ExecPartnerWebhook?Action=CreateSubscription', @@ -141,6 +142,8 @@ export function SettingsPartner() { label: event, value: event, })), + standardsExcludeAllTenants: + webhookConfig?.data?.Results?.standardsExcludeAllTenants, }} render={({ handleSubmit }) => ( <> @@ -156,6 +159,14 @@ export function SettingsPartner() { refreshFunction={() => webhookEvents.refetch()} helpText="Select the events you want to receive notifications for." /> + Date: Wed, 15 May 2024 18:47:26 +0200 Subject: [PATCH 89/92] add member to role update --- src/data/AuditLogTemplates.json | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index d4a274e4f754..957819ef53a0 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -87,7 +87,23 @@ { "value": "Add member to role.", "name": "A user has been added to an admin role", - "template": [] + "template": { + "preset": { + "value": "Add member to role.", + "label": "A user has been added to an admin role" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals to" }, + "Input": { + "value": "Add member to role.", + "label": "Add member to role." + } + } + ] + } }, { "value": "Update StsRefreshTokenValidFrom Timestamp.", From a9effcdd8eba1d7f1d1379b1a5903161cf412273 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 May 2024 18:52:58 +0200 Subject: [PATCH 90/92] strong authentication --- src/data/AuditLogSchema.json | 3 +++ src/data/AuditLogTemplates.json | 36 +++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/data/AuditLogSchema.json b/src/data/AuditLogSchema.json index 1051d7b758cc..d29cdb5cffea 100644 --- a/src/data/AuditLogSchema.json +++ b/src/data/AuditLogSchema.json @@ -100,6 +100,9 @@ { "value": "remove delegation entry.", "name": "removed delegation entry" }, { "value": "remove domain from company.", "name": "removed domain from company" }, { "value": "remove member from group.", "name": "removed member from group" }, + { "value": "remove member from a role.", "name": "remove member from a role" }, + { "value": "Disable Strong Authentication.", "name": "Disable Strong Authentication." }, + { "value": "remove service principal.", "name": "removed a service principal from the directory" diff --git a/src/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json index 957819ef53a0..3b90b5eaedba 100644 --- a/src/data/AuditLogTemplates.json +++ b/src/data/AuditLogTemplates.json @@ -129,12 +129,44 @@ { "value": "Disable Strong Authentication.", "name": "A users MFA has been disabled", - "template": [] + "template": { + "preset": { + "value": "Disable Strong Authentication.", + "label": "A users MFA has been disabled" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals to" }, + "Input": { + "value": "Disable Strong Authentication.", + "label": "Disable Strong Authentication." + } + } + ] + } }, { "value": "Remove Member from a role.", "name": "A user has been removed from a role", - "template": [] + "template": { + "preset": { + "value": "Remove Member from a role.", + "label": "A user has been removed from a role" + }, + "logbook": { "value": "Audit.AzureActiveDirectory", "label": "Azure AD" }, + "conditions": [ + { + "Property": { "value": "List:Operation", "label": "Operation" }, + "Operator": { "value": "EQ", "label": "Equals to" }, + "Input": { + "value": "Remove Member from a role.", + "label": "Remove Member from a role." + } + } + ] + } }, { "value": "Reset user password.", From fcb2b70838f2890cab0b470658f09b2f8cc59bdb Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 15 May 2024 13:56:41 -0400 Subject: [PATCH 91/92] Dashboard - Clickable user chart --- src/views/home/Home.jsx | 67 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/src/views/home/Home.jsx b/src/views/home/Home.jsx index f764cfc32915..432bd10e0870 100644 --- a/src/views/home/Home.jsx +++ b/src/views/home/Home.jsx @@ -2,10 +2,8 @@ import React, { useState } from 'react' import { faBook, faCog, - faEllipsisH, faLaptopCode, faMailBulk, - faSearch, faUser, faUserFriends, faUserPlus, @@ -16,19 +14,15 @@ import { CCol, CCollapse, CDropdown, - CDropdownHeader, - CDropdownItem, CDropdownMenu, CDropdownToggle, CLink, - CNav, CRow, } from '@coreui/react' import { useGenericGetRequestQuery } from 'src/store/api/app' import { CippContentCard } from 'src/components/layout' import Skeleton from 'react-loading-skeleton' import { UniversalSearch } from 'src/components/utilities/UniversalSearch' -import { ActionContentCard } from 'src/components/contentcards' import { useSelector } from 'react-redux' import allStandardsList from 'src/data/standards' import Portals from 'src/data/portals' @@ -37,11 +31,14 @@ import { CChart } from '@coreui/react-chartjs' import { getStyle } from '@coreui/utils' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { Link } from 'react-router-dom' -import CippPrettyCard from 'src/components/contentcards/CippPrettyCard' +import { useNavigate } from 'react-router-dom' +import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat' +import { ModalService } from 'src/components/utilities' const TenantDashboard = () => { const [visible, setVisible] = useState(false) const [domainVisible, setDomainVisible] = useState(false) + const navigate = useNavigate() const currentTenant = useSelector((state) => state.app.currentTenant) const theme = useSelector((state) => state.app.currentTheme) @@ -174,6 +171,55 @@ const TenantDashboard = () => { ) }) } + + const handleTable = (data, title) => { + const QueryColumns = [] + const columns = Object.keys(data[0]).map((key) => { + QueryColumns.push({ + name: key, + selector: (row) => row[key], // Accessing the property using the key + sortable: true, + exportSelector: key, + cell: cellGenericFormatter(), + }) + }) + ModalService.open({ + data: data, + componentType: 'table', + componentProps: { + columns: QueryColumns, + keyField: 'id', + }, + title: title, + size: 'lg', + }) + } + + const userChartLegendClickHandler = function (e, legendItem, legend) { + switch (legendItem.text) { + case 'Total Users': + navigate('/identity/administration/users?customerId=' + currentTenant.customerId) + break + case 'Licensed Users': + navigate( + '/identity/administration/users?customerId=' + + currentTenant.customerId + + '&tableFilter=Graph%3A+assignedLicenses%2F%24count+ne+0', + ) + break + case 'Guests': + navigate( + '/identity/administration/users?customerId=' + + currentTenant.customerId + + '&tableFilter=Graph%3A+usertype+eq+%27guest%27', + ) + break + case 'Global Admins': + handleTable(GlobalAdminList.data?.Results, 'Global Admins') + break + } + } + return ( <> @@ -337,6 +383,13 @@ const TenantDashboard = () => { labels: { color: getStyle('--cui-body-color'), }, + onClick: userChartLegendClickHandler, + onHover: (event) => { + event.native.target.style.cursor = 'pointer' + }, + onLeave: (event) => { + event.native.target.style.cursor = 'default' + }, }, }, }} From 7a7a8ca1ac06c236eaec69308b5e11f0da4b4e11 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 May 2024 20:18:40 +0200 Subject: [PATCH 92/92] version up --- package.json | 2 +- public/version_latest.txt | 2 +- version_latest.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 616ab46b1e64..332ac7504f6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cipp", - "version": "5.6.2", + "version": "5.7.0", "description": "The CyberDrain Improved Partner Portal is a portal to help manage administration for Microsoft Partners.", "homepage": "https://cipp.app/", "bugs": { diff --git a/public/version_latest.txt b/public/version_latest.txt index d6a86bf436c0..42cdd0b540f9 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -5.6.2 +5.7.0 diff --git a/version_latest.txt b/version_latest.txt index d6a86bf436c0..42cdd0b540f9 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -5.6.2 +5.7.0