diff --git a/src/views/cipp/app-settings/SettingsSuperAdmin.jsx b/src/views/cipp/app-settings/SettingsSuperAdmin.jsx index 4e38038fb68c..18cb6b397980 100644 --- a/src/views/cipp/app-settings/SettingsSuperAdmin.jsx +++ b/src/views/cipp/app-settings/SettingsSuperAdmin.jsx @@ -7,6 +7,7 @@ import { CippCallout } from 'src/components/layout/index.js' import CippAccordionItem from 'src/components/contentcards/CippAccordionItem' import SettingsCustomRoles from 'src/views/cipp/app-settings/components/SettingsCustomRoles' import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import SettingsSAMRoles from './components/SettingsSAMRoles' export function SettingsSuperAdmin() { const partnerConfig = useGenericGetRequestQuery({ @@ -65,46 +66,11 @@ export function SettingsSuperAdmin() {

- - -

Tenant Mode

-
( - <> - {partnerConfig.isFetching && } - - - - - - - )} - /> - {webhookCreateResult.isSuccess && ( - - {webhookCreateResult?.data?.results} - - )} - - + ) } diff --git a/src/views/cipp/app-settings/components/SettingsSAMRoles.jsx b/src/views/cipp/app-settings/components/SettingsSAMRoles.jsx new file mode 100644 index 000000000000..ebc8310b6abd --- /dev/null +++ b/src/views/cipp/app-settings/components/SettingsSAMRoles.jsx @@ -0,0 +1,150 @@ +import React, { useEffect, useRef, useState } from 'react' +import { + CButton, + CCallout, + CCol, + CForm, + CRow, + CAccordion, + CAccordionHeader, + CAccordionBody, + CAccordionItem, +} from '@coreui/react' +import { Field, Form, FormSpy } from 'react-final-form' +import { RFFCFormRadioList, RFFSelectSearch } from 'src/components/forms' +import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { TenantSelectorMultiple, ModalService, CippOffcanvas } from 'src/components/utilities' +import PropTypes from 'prop-types' +import { OnChange } from 'react-final-form-listeners' +import { useListTenantsQuery } from 'src/store/api/tenants' +import { OffcanvasListSection } from 'src/components/utilities/CippListOffcanvas' +import CippButtonCard from 'src/components/contentcards/CippButtonCard' +import GDAPRoles from 'src/data/GDAPRoles' + +const SettingsSAMRoles = () => { + const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery() + const [selectedTenant, setSelectedTenant] = useState([]) + const tenantSelectorRef = useRef() + const { + data: tenants = [], + isFetching: tenantsFetching, + isSuccess: tenantSuccess, + } = useListTenantsQuery({ + showAllTenantSelector: true, + }) + + const { + data: cippSAMRoles = [], + isFetching: roleListFetching, + isSuccess: roleListSuccess, + refetch: refetchRoleList, + } = useGenericGetRequestQuery({ + path: 'api/ExecSAMRoles', + }) + + const handleTenantChange = (e) => { + setSelectedTenant(e) + } + + const handleSubmit = async (values) => { + //filter on only objects that are 'true' + genericPostRequest({ + path: '/api/ExecSAMRoles?Action=Update', + values: { + Roles: values.Roles, + Tenants: selectedTenant.map((tenant) => tenant.value), + }, + }).then(() => { + refetchRoleList() + }) + } + + useEffect(() => { + if (roleListSuccess && cippSAMRoles.Tenants.length > 0) { + var selectedTenants = [] + tenants.map((tenant) => { + if (cippSAMRoles.Tenants.includes(tenant.customerId)) { + selectedTenants.push({ label: tenant.displayName, value: tenant.customerId }) + } + }) + tenantSelectorRef.current.setValue(selectedTenants) + } + }, [cippSAMRoles, roleListSuccess, tenantSuccess, tenantSelectorRef, tenants]) + + return ( + + <> +

+ Add your CIPP-SAM application Service Principal directly to Admin Roles in the tenant. + This is an advanced use case where you need access to additional Graph endpoints or + Exchange Cmdlets otherwise unavailable via Delegated permissions. +

+

+ This functionality is in + beta and should be treated as such. Roles are added during the Update Permissions process + or a CPV refresh. +

+ + {roleListSuccess && ( + { + return ( + + + +
+ ({ + name: role.Name, + value: role.ObjectId, + }))} + multi={true} + refreshFunction={() => refetchRoleList()} + placeholder="Select admin roles" + /> +
+
+
Selected Tenants
+ handleTenantChange(e)} + /> +
+
+
+ + {postResults.isSuccess && ( + {postResults.data.Results} + )} + + + + + Save + + + + +
+ ) + }} + /> + )} + +
+ ) +} + +export default SettingsSAMRoles diff --git a/src/views/identity/administration/Users.jsx b/src/views/identity/administration/Users.jsx index 3bd663d7e063..669e401a3611 100644 --- a/src/views/identity/administration/Users.jsx +++ b/src/views/identity/administration/Users.jsx @@ -589,7 +589,7 @@ const Users = (row) => { label: 'Revoke sessions', color: 'info', modal: true, - modalUrl: `/api/ExecRevokeSessions?Enable=true&TenantFilter=!Tenant&ID=!userPrincipalName`, + modalUrl: `/api/ExecRevokeSessions?Enable=true&TenantFilter=!Tenant&ID=!id&Username=!userPrincipalName`, modalMessage: 'Are you sure you want to revoke all sessions for these users?', }, { diff --git a/src/views/tenant/administration/SecureScore.jsx b/src/views/tenant/administration/SecureScore.jsx index be036997339c..bfa9d2e751c2 100644 --- a/src/views/tenant/administration/SecureScore.jsx +++ b/src/views/tenant/administration/SecureScore.jsx @@ -28,6 +28,8 @@ import { CellTip, cellGenericFormatter } from 'src/components/tables/CellGeneric import { CippCallout } from 'src/components/layout' import CippPrettyCard from 'src/components/contentcards/CippPrettyCard' import { TableModalButton } from 'src/components/buttons' +import DOMPurify from 'dompurify' +import ReactHtmlParser from 'react-html-parser' const SecureScore = () => { const textRef = useRef() @@ -66,6 +68,12 @@ const SecureScore = () => { }, }) + const sanitizeHtml = (html) => { + var sanitizedHtml = DOMPurify.sanitize(html) + var parsedHtml = ReactHtmlParser(sanitizedHtml) + return parsedHtml + } + useEffect(() => { if (isSuccess) { setTranslatedData(securescore.Results[0]) @@ -341,23 +349,16 @@ const SecureScore = () => {
Description
-
+
+ {sanitizeHtml(`${info.description} ${info.implementationStatus}`)} +
{info.scoreInPercentage !== 100 && (
Remediation Recommendation
- { -
- } + {
{sanitizeHtml(info.remediation)}
}
)} diff --git a/staticwebapp.config.json b/staticwebapp.config.json index 74988468595b..0c36ddcac257 100644 --- a/staticwebapp.config.json +++ b/staticwebapp.config.json @@ -103,7 +103,7 @@ } }, "globalHeaders": { - "content-security-policy": "default-src https: 'unsafe-eval' 'unsafe-inline'; object-src 'self' blob:; img-src 'self' blob: data: *" + "content-security-policy": "default-src https: blob: 'unsafe-eval' 'unsafe-inline'; object-src 'self' blob:; img-src 'self' blob: data: *" }, "mimeTypes": { ".json": "text/json"