From 3b78518028128ae34cd090ee6e048a7dfbe72bf0 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 10 Apr 2024 15:49:09 -0400 Subject: [PATCH 1/3] Update augmentt link --- src/components/layout/AppFooter.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/layout/AppFooter.jsx b/src/components/layout/AppFooter.jsx index 2a736bc8439a..6437061d9133 100644 --- a/src/components/layout/AppFooter.jsx +++ b/src/components/layout/AppFooter.jsx @@ -30,7 +30,11 @@ const AppFooter = () => { - + From 5889082481037dd3080b4d50c3f8f4ea66ea9237 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 10 Apr 2024 18:06:56 -0400 Subject: [PATCH 2/3] Partner webhooks --- src/views/cipp/app-settings/CIPPSettings.jsx | 24 ++- .../cipp/app-settings/SettingsPartner.jsx | 152 ++++++++++++++++++ 2 files changed, 168 insertions(+), 8 deletions(-) create mode 100644 src/views/cipp/app-settings/SettingsPartner.jsx diff --git a/src/views/cipp/app-settings/CIPPSettings.jsx b/src/views/cipp/app-settings/CIPPSettings.jsx index ff43ad2a5a94..c1e6b9463fd7 100644 --- a/src/views/cipp/app-settings/CIPPSettings.jsx +++ b/src/views/cipp/app-settings/CIPPSettings.jsx @@ -11,6 +11,7 @@ import { SettingsLicenses } from 'src/views/cipp/app-settings/SettingsLicenses.j import { SettingsExtensions } from 'src/views/cipp/app-settings/SettingsExtensions.jsx' import { SettingsMaintenance } from 'src/views/cipp/app-settings/SettingsMaintenance.jsx' import { SettingsExtensionMappings } from 'src/views/cipp/app-settings/SettingsExtensionMappings.jsx' +import { SettingsPartner } from 'src/views/cipp/app-settings/SettingsPartner.jsx' /** * This function returns the settings page content for CIPP. @@ -35,15 +36,18 @@ export default function CIPPSettings() { Notifications setActive(5)} href="#"> - Licenses + Partner Webhooks setActive(6)} href="#"> - Maintenance + Licenses setActive(7)} href="#"> - Extensions + Maintenance setActive(8)} href="#"> + Extensions + + setActive(9)} href="#"> Extension Mappings @@ -68,22 +72,26 @@ export default function CIPPSettings() { - - - + + - + - + + + + + + diff --git a/src/views/cipp/app-settings/SettingsPartner.jsx b/src/views/cipp/app-settings/SettingsPartner.jsx new file mode 100644 index 000000000000..e56b479cc7a2 --- /dev/null +++ b/src/views/cipp/app-settings/SettingsPartner.jsx @@ -0,0 +1,152 @@ +import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' +import { + CBadge, + CButton, + CCallout, + CCard, + CCardBody, + CCardHeader, + CCardTitle, + CCol, + CForm, + CRow, + CSpinner, +} from '@coreui/react' +import { Form, useForm } from 'react-final-form' +import { RFFCFormInput, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms/index.js' +import React, { useEffect, useState } from 'react' +import { CippCallout } from 'src/components/layout/index.js' +import { CippCodeBlock } from 'src/components/utilities' +import { CellDate } from 'src/components/tables' + +/** + * Sets the notification settings. + * @returns {JSX.Element} The notification settings component. + */ +export function SettingsPartner() { + const webhookConfig = useGenericGetRequestQuery({ + path: '/api/ExecPartnerWebhook', + params: { Action: 'ListSubscription' }, + }) + const webhookEvents = useGenericGetRequestQuery({ + path: '/api/ExecPartnerWebhook', + params: { Action: 'ListEventTypes' }, + }) + const [submitWebhook, webhookCreateResult] = useLazyGenericPostRequestQuery() + + const onSubmit = (values) => { + const shippedValues = { + EventType: values?.EventType?.map((event) => event.value), + } + submitWebhook({ + path: '/api/ExecPartnerWebhook?Action=CreateSubscription', + values: shippedValues, + }).then((res) => { + webhookConfig.refetch() + }) + } + + return ( + + + + <> + webhookConfig.refetch()} + className="mb-2" + disabled={webhookConfig.isFetching} + > + {webhookConfig.isFetching ? ( + <> + Loading... + + ) : ( + <> + + Refresh + + )} + + + {!webhookConfig.isFetching && webhookConfig.error && ( + Error loading data + )} + {webhookConfig.isSuccess && ( + <> +

Webhook Configuration

+ + +

Webhook URL

+ +
+ +

Last Updated

+ +
+ +

Subscribed Events

+
({ + label: event, + value: event, + })), + }} + render={({ handleSubmit }) => ( + <> + + ({ + name: event, + value: event, + }))} + multi={true} + refreshFunction={() => webhookEvents.refetch()} + helpText="Select the events you want to receive notifications for." + /> + + {webhookCreateResult.isFetching ? ( + <> + + Saving... + + ) : ( + 'Save' + )} + + + + )} + /> + {webhookCreateResult.isSuccess && ( + + {webhookCreateResult?.data?.Results} + + )} + + + + )} + + + + ) +} From ebcc929cd9de1b629a66b44b83c15a6fca399b3d Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 10 Apr 2024 19:58:29 -0400 Subject: [PATCH 3/3] Add webhook testing --- .../cipp/app-settings/SettingsPartner.jsx | 131 ++++++++++++++++-- 1 file changed, 123 insertions(+), 8 deletions(-) diff --git a/src/views/cipp/app-settings/SettingsPartner.jsx b/src/views/cipp/app-settings/SettingsPartner.jsx index e56b479cc7a2..91f45d98c11e 100644 --- a/src/views/cipp/app-settings/SettingsPartner.jsx +++ b/src/views/cipp/app-settings/SettingsPartner.jsx @@ -1,6 +1,9 @@ -import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js' +import { + useGenericGetRequestQuery, + useLazyGenericGetRequestQuery, + useLazyGenericPostRequestQuery, +} from 'src/store/api/app.js' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faCircleNotch } from '@fortawesome/free-solid-svg-icons' import { CBadge, CButton, @@ -11,12 +14,13 @@ import { CCardTitle, CCol, CForm, + CLink, CRow, CSpinner, } from '@coreui/react' -import { Form, useForm } from 'react-final-form' -import { RFFCFormInput, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms/index.js' -import React, { useEffect, useState } from 'react' +import { Form } from 'react-final-form' +import { 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' import { CellDate } from 'src/components/tables' @@ -35,6 +39,8 @@ export function SettingsPartner() { params: { Action: 'ListEventTypes' }, }) const [submitWebhook, webhookCreateResult] = useLazyGenericPostRequestQuery() + const [sendTest, sendTestResult] = useLazyGenericGetRequestQuery() + const [checkTest, checkTestResult] = useLazyGenericGetRequestQuery() const onSubmit = (values) => { const shippedValues = { @@ -48,6 +54,25 @@ export function SettingsPartner() { }) } + useEffect(() => { + if ( + sendTestResult.isSuccess && + sendTestResult?.data?.Results?.correlationId && + !checkTestResult?.data?.Results?.results + ) { + setTimeout( + checkTest({ + path: '/api/ExecPartnerWebhook', + params: { + Action: 'ValidateTest', + CorrelationId: sendTestResult?.data?.Results?.correlationId, + }, + }), + 1000, + ) + } + }, [sendTestResult, checkTest, checkTestResult]) + return ( @@ -77,11 +102,25 @@ export function SettingsPartner() { {webhookConfig.isSuccess && ( <>

Webhook Configuration

+ + + Subscribe to Microsoft Partner center webhooks to enable automatic tenant + onboarding and alerting. Updating the settings will replace any existing webhook + subscription with one pointing to CIPP. Refer to the{' '} + + Microsoft Partner Center documentation + {' '} + for more information on the webhook types. + +

Webhook URL

@@ -93,7 +132,7 @@ export function SettingsPartner() { format="short" />
- +

Subscribed Events

{webhookCreateResult.isFetching ? ( @@ -143,6 +182,82 @@ export function SettingsPartner() { )}
+

Webhook Test

+ + + + sendTest({ + path: '/api/ExecPartnerWebhook', + params: { Action: 'SendTest' }, + }) + } + > + {sendTestResult.isFetching ? ( + <> + + Running Test... + + ) : ( + 'Start Test' + )} + + {checkTestResult.isFetching && !checkTestResult?.data?.Results?.result && ( + <> + Waiting for results + + )} + + + + {checkTestResult.isSuccess && ( + <> + +

Status

+ {checkTestResult?.data?.Results.status} +
+ {Array.isArray(checkTestResult?.data?.Results?.results) && ( + <> + +

Status Code

+ + {checkTestResult?.data?.Results?.results[0].responseCode} +
+ {checkTestResult?.data?.Results?.results[0].responseMessage !== '' && ( + +

Response Message

+ {checkTestResult.data.Results.results[0].responseMessage} +
+ )} + +

Date/Time

+ +
+ + )} + + )} +
)}