diff --git a/package-lock.json b/package-lock.json
index 232261d7bcc3..490fb9a392b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cipp",
- "version": "5.5.0",
+ "version": "5.6.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cipp",
- "version": "5.5.0",
+ "version": "5.6.1",
"license": "AGPL-3.0",
"dependencies": {
"@coreui/chartjs": "^3.0.0",
@@ -46,6 +46,7 @@
"react": "^18.2.0",
"react-app-polyfill": "^2.0.0",
"react-bootstrap": "^1.6.5",
+ "react-circular-progressbar": "^2.1.0",
"react-copy-to-clipboard": "^5.1.0",
"react-data-table-component": "^7.4.5",
"react-datepicker": "^4.10.0",
@@ -6864,6 +6865,14 @@
"react-dom": ">=16.8.0"
}
},
+ "node_modules/react-circular-progressbar": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/react-circular-progressbar/-/react-circular-progressbar-2.1.0.tgz",
+ "integrity": "sha512-xp4THTrod4aLpGy68FX/k1Q3nzrfHUjUe5v6FsdwXBl3YVMwgeXYQKDrku7n/D6qsJA9CuunarAboC2xCiKs1g==",
+ "peerDependencies": {
+ "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-copy-to-clipboard": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz",
diff --git a/package.json b/package.json
index 5286527775d3..332ac7504f6e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cipp",
- "version": "5.6.1",
+ "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": {
@@ -64,6 +64,7 @@
"react": "^18.2.0",
"react-app-polyfill": "^2.0.0",
"react-bootstrap": "^1.6.5",
+ "react-circular-progressbar": "^2.1.0",
"react-copy-to-clipboard": "^5.1.0",
"react-data-table-component": "^7.4.5",
"react-datepicker": "^4.10.0",
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.",
diff --git a/public/version_latest.txt b/public/version_latest.txt
index b7c75422bc1d..42cdd0b540f9 100644
--- a/public/version_latest.txt
+++ b/public/version_latest.txt
@@ -1 +1 @@
-5.6.1
+5.7.0
diff --git a/src/_nav.jsx b/src/_nav.jsx
index 01007acb414a..902a8390b79f 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',
@@ -155,7 +150,7 @@ const _nav = [
{
component: CNavItem,
name: 'Tenant Onboarding',
- to: '/tenant/administration/tenant-onboarding-wizard',
+ to: '/tenant/administration/tenant-onboarding',
},
{
component: CNavItem,
@@ -707,6 +702,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/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/components/contentcards/CippButtonCard.jsx b/src/components/contentcards/CippButtonCard.jsx
index 1540c09a888f..4a6400ad9cca 100644
--- a/src/components/contentcards/CippButtonCard.jsx
+++ b/src/components/contentcards/CippButtonCard.jsx
@@ -1,7 +1,7 @@
import React from 'react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { CCard, CCardBody, CCardFooter, CCardHeader, CCardTitle } from '@coreui/react'
import Skeleton from 'react-loading-skeleton'
+import PropTypes from 'prop-types'
export default function CippButtonCard({
title,
@@ -25,3 +25,11 @@ export default function CippButtonCard({
)
}
+
+CippButtonCard.propTypes = {
+ title: PropTypes.string.isRequired,
+ titleType: PropTypes.string,
+ CardButton: PropTypes.element.isRequired,
+ children: PropTypes.element.isRequired,
+ isFetching: PropTypes.bool.isRequired,
+}
diff --git a/src/components/contentcards/CippChartCard.jsx b/src/components/contentcards/CippChartCard.jsx
new file mode 100644
index 000000000000..c708ef8e51ad
--- /dev/null
+++ b/src/components/contentcards/CippChartCard.jsx
@@ -0,0 +1,86 @@
+import React from 'react'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+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'
+
+export default function CippChartCard({
+ title,
+ titleType = 'normal',
+ ChartData,
+ ChartLabels,
+ ChartType = 'pie',
+ LegendLocation = 'bottom',
+ isFetching,
+ refreshFunction,
+}) {
+ return (
+
+
+
+ {titleType === 'big' ? {title} : title}
+ {refreshFunction ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+ {ChartData && (
+
+ )}
+
+
+ )
+}
+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/components/contentcards/CippPrettyCard.jsx b/src/components/contentcards/CippPrettyCard.jsx
new file mode 100644
index 000000000000..b97516e3713c
--- /dev/null
+++ b/src/components/contentcards/CippPrettyCard.jsx
@@ -0,0 +1,46 @@
+import React from 'react'
+import { CCard, CCardBody, CCardFooter, CCardHeader, CCardTitle, CCol, CRow } from '@coreui/react'
+import Skeleton from 'react-loading-skeleton'
+import { CircularProgressbar } from 'react-circular-progressbar'
+import 'react-circular-progressbar/dist/styles.css'
+
+export default function CippPrettyCard({
+ title,
+ titleType = 'normal',
+ percentage,
+ topLabel,
+ smallLabel,
+ ringcolor = '#f89226',
+ isFetching,
+}) {
+ return (
+
+
+
+ {titleType === 'big' ? {title} : title}
+
+
+
+ {isFetching && }
+ {!isFetching && (
+
+
+
+
+
+
+
+ {topLabel}
+ {smallLabel}
+
+
+ )}
+
+
+ )
+}
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,
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/components/tables/CellTable.jsx b/src/components/tables/CellTable.jsx
index 0fffd6da5637..cfcbd5403065 100644
--- a/src/components/tables/CellTable.jsx
+++ b/src/components/tables/CellTable.jsx
@@ -20,20 +20,24 @@ export default function cellTable(
columnProp = column
}
- if (!Array.isArray(columnProp) && typeof columnProp === 'object') {
- columnProp = Object.keys(columnProp).map((key) => {
- return {
- Key: key,
- Value: columnProp[key],
- }
- })
+ if (columnProp === undefined || columnProp === null) {
+ columnProp = []
} else {
- if (Array.isArray(columnProp) && typeof columnProp[0] !== 'object') {
- columnProp = columnProp.map((row) => {
+ if (!Array.isArray(columnProp) && typeof columnProp === 'object') {
+ columnProp = Object.keys(columnProp).map((key) => {
return {
- Value: row,
+ Key: key,
+ Value: columnProp[key],
}
})
+ } else {
+ if (Array.isArray(columnProp) && typeof columnProp[0] !== 'object') {
+ columnProp = columnProp.map((row) => {
+ return {
+ Value: row,
+ }
+ })
+ }
}
}
diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx
index 3ba432f63677..f3ea486ee243 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 }) => (
<>
@@ -124,6 +125,7 @@ export default function CippTable({
filterlist,
showFilter = true,
endpointName,
+ defaultSortAsc = true,
tableProps: {
keyField = 'id',
theme = 'cyberdrain',
@@ -614,7 +616,7 @@ export default function CippTable({
className="m-1"
size="sm"
>
-
+
,
])
@@ -888,7 +890,7 @@ export default function CippTable({
{(updatedColumns || !dynamicColumns) && (
<>
{(massResults.length >= 1 || loopRunning) && (
-
+
{massResults[0]?.data?.Metadata?.Heading && (
{massResults.map((message, idx) => {
@@ -963,7 +965,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/components/utilities/CippCopyToClipboard.jsx b/src/components/utilities/CippCopyToClipboard.jsx
index 064392d9b4fa..fa930968f7a6 100644
--- a/src/components/utilities/CippCopyToClipboard.jsx
+++ b/src/components/utilities/CippCopyToClipboard.jsx
@@ -14,7 +14,7 @@ function CippCopyToClipboard({ text }) {
onCodeCopied()}>
diff --git a/src/components/utilities/CippTableOffcanvas.jsx b/src/components/utilities/CippTableOffcanvas.jsx
index bc603ecdfda4..236ccff04b4e 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 && data?.length > 0) {
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 ? (
) : (
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/data/AuditLogSchema.json b/src/data/AuditLogSchema.json
new file mode 100644
index 000000000000..d29cdb5cffea
--- /dev/null
+++ b/src/data/AuditLogSchema.json
@@ -0,0 +1,969 @@
+{
+ "Common": {
+ "Id": "String",
+ "RecordType": "List:AuditLogRecordType",
+ "CreationTime": "String",
+ "Operation": "List:Operation",
+ "OrganizationId": "String",
+ "UserType": "List:UserType",
+ "UserKey": "String",
+ "Workload": "String",
+ "ResultStatus": "String",
+ "ObjectId": "String",
+ "UserId": "String",
+ "ClientIP": "String",
+ "Username": "String",
+ "CIPPGeoLocation": "List:countryList",
+ "CIPPBadRepIP": "String",
+ "CIPPHostedIP": "String",
+ "CIPPIPDetected": "String"
+ },
+ "Audit.Exchange": {
+ "Id": "Combination GUID",
+ "RecordType": "List:AuditLogRecordType",
+ "CreationTime": "String",
+ "Operation": "List:Operation",
+ "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",
+ "MoveToFolder": "String"
+ },
+ "Audit.AzureActiveDirectory": {
+ "AzureActiveDirectoryEventType": "List:AzureActiveDirectoryEventType",
+ "AccountEnabled": "String",
+ "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: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" },
+ { "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 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"
+ },
+ {
+ "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" },
+ {
+ "value": "Update StsRefreshTokenValidFrom Timestamp.",
+ "name": "Update StsRefreshTokenValidFrom Timestamp."
+ }
+ ],
+ "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." }
+ ],
+ "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." }
+ ],
+ "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/data/AuditLogTemplates.json b/src/data/AuditLogTemplates.json
new file mode 100644
index 000000000000..3b90b5eaedba
--- /dev/null
+++ b/src/data/AuditLogTemplates.json
@@ -0,0 +1,317 @@
+[
+ {
+ "value": "New-InboxRule",
+ "name": "A new Inbox rule is created",
+ "template": {
+ "preset": { "value": "New-InboxRule", "label": "A new Inbox rule is created" },
+ "logbook": { "value": "Audit.Exchange", "label": "Exchange" },
+ "conditions": [
+ {
+ "Property": { "value": "List:Operation", "label": "Operation" },
+ "Operator": { "value": "EQ", "label": "Equals to" },
+ "Input": {
+ "value": "new-inboxrule",
+ "label": "created new inbox rule in outlook web app"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "value": "New-InboxRuleRSS",
+ "name": "A new Inbox rule is created that forwards e-mails to the RSS feeds folder",
+ "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 to" },
+ "Input": {
+ "value": "new-inboxrule",
+ "label": "created new inbox rule in outlook web app"
+ }
+ },
+ {
+ "Property": { "value": "String", "label": "MoveToFolder" },
+ "Operator": { "value": "like", "label": "Like" },
+ "Input": { "value": "*RSS*" }
+ }
+ ]
+ }
+ },
+ {
+ "value": "Set-InboxRule",
+ "name": "A existing Inbox rule is edited",
+ "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 to" },
+ "Input": {
+ "value": "set-inboxrule",
+ "label": "Updated inbox rule in outlook web app"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "value": "Set-InboxRuleRSS",
+ "name": "A existing Inbox rule is edited that forwards e-mails to the RSS feeds folder",
+ "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 to" },
+ "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": {
+ "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.",
+ "name": "A user sessions have been revoked",
+ "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 to" },
+ "Input": {
+ "value": "Update StsRefreshTokenValidFrom Timestamp.",
+ "label": "Update StsRefreshTokenValidFrom Timestamp."
+ }
+ }
+ ]
+ }
+ },
+ {
+ "value": "Disable Strong Authentication.",
+ "name": "A users MFA has been disabled",
+ "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": {
+ "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.",
+ "name": "A user password has been reset",
+ "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 to" },
+ "Input": {
+ "value": "Reset user password.",
+ "label": "Reset user password."
+ }
+ }
+ ]
+ }
+ },
+ {
+ "value": "UserLoggedInFromUnknownLocation",
+ "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:Operation", "label": "Operation" },
+ "Operator": { "value": "EQ", "label": "Equals to" },
+ "Input": {
+ "value": "UserLoggedIn",
+ "label": "A user logged in"
+ }
+ },
+ {
+ "Property": { "value": "List:countryList", "label": "CIPPGeoLocation", "multi": true },
+ "Operator": { "value": "NotIn", "label": "Not In" }
+ }
+ ]
+ }
+ },
+ {
+ "value": "Add service principal.",
+ "name": "A service principal has been created",
+ "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": {
+ "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",
+ "name": "A user has logged in a using a known VPN, Proxy, Or anonymizer",
+ "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": "List:Operation", "label": "Operation" },
+ "Operator": { "value": "EQ", "label": "Equals to" },
+ "Input": {
+ "value": "UserLoggedIn",
+ "label": "A user logged in"
+ }
+ },
+ {
+ "Property": { "value": "String", "label": "CIPPBadRepIP" },
+ "Operator": { "value": "EQ", "label": "Equals to" },
+ "Input": {
+ "value": "true",
+ "label": "true"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "value": "HostedIP",
+ "name": "A user has logged in a using a known hosting provider IP",
+ "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": "List:Operation", "label": "Operation" },
+ "Operator": { "value": "EQ", "label": "Equals to" },
+ "Input": {
+ "value": "UserLoggedIn",
+ "label": "A user logged in"
+ }
+ },
+ {
+ "Property": { "value": "String", "label": "CIPPHostedIP" },
+ "Operator": { "value": "EQ", "label": "Equals to" },
+ "Input": {
+ "value": "true",
+ "label": "true"
+ }
+ }
+ ]
+ }
+ }
+]
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.",
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/data/standards.json b/src/data/standards.json
index 2766676a8ce5..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",
@@ -487,6 +538,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",
@@ -1236,7 +1317,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/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"
+ }
+]
diff --git a/src/importsMap.jsx b/src/importsMap.jsx
index 741d722bc721..fd44014ae9c7 100644
--- a/src/importsMap.jsx
+++ b/src/importsMap.jsx
@@ -1,142 +1,146 @@
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')),
- "/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/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": React.lazy(() => import('./views/tenant/administration/TenantOnboarding')),
+ "/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/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])
diff --git a/src/routes.json b/src/routes.json
index 4c9a675a515d..e681555e0346 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/email-exchange/rooms/ListRooms",
+ "allowedRoles": ["admin", "editor", "readonly"]
+ },
+ {
+ "path": "/rooms/management/room-lists",
+ "name": "Room Lists",
+ "component": "views/email-exchange/rooms/ListRoomLists",
+ "allowedRoles": ["admin", "editor", "readonly"]
+ },
{
"path": "/email/tools/mailbox-restore-wizard",
"name": "Mailbox Restore Wizard",
@@ -774,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",
@@ -936,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/cipp/Setup.jsx b/src/views/cipp/Setup.jsx
index c0a728ff8ec7..bf09e8b04baf 100644
--- a/src/views/cipp/Setup.jsx
+++ b/src/views/cipp/Setup.jsx
@@ -6,7 +6,12 @@ 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) {
const savedCallback = useRef()
@@ -49,11 +54,7 @@ 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 [checkPermissions, permissionsResult] = useLazyExecPermissionsAccessCheckQuery()
const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
const [genericGetRequest, getResults] = useLazyGenericGetRequestQuery()
const onSubmit = (values) => {
@@ -72,7 +73,6 @@ const Setup = () => {
path: 'api/ExecSAMSetup',
params: { CreateSAM: true, partnersetup: true },
})
- setSetupdone(false)
}
useInterval(
@@ -82,19 +82,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 & Approving Application' },
+ { id: 3, text: 'Step 3 - Receiving Token' },
+ { id: 4, text: 'Step 4 - Finishing Authentication Setup' },
+ ]
+ const RenderSteps = ({ currentStep = 0 }) => (
+ <>
+ {currentStep > 0 &&
+ stepsDetails.slice(0, currentStep - 1).map((step) => (
+
+ {step.text} - Completed
+
+ ))}
+ >
+ )
return (
@@ -112,7 +128,7 @@ const Setup = () => {
rel="noreferrer"
target="_blank"
>
- here.
+ here
@@ -134,7 +150,11 @@ const Setup = () => {
-
+
Step 2
Enter the secure application model credentials.
@@ -144,32 +164,49 @@ 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' })}
- {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. 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.
+
{
className="btn btn-primary"
type="button"
onClick={() => startCIPPSetup(true)}
- validate={() => valbutton()}
>
- Start Setup Wizard
+ {getResults.isFetching && } 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 && getResults.data?.step < 5 && (
+ <>
+ Step {getResults.data?.step} - {getResults.data.message}{' '}
+ {getResults.data.url && (
+
+ HERE
+
+ )}
+ >
)}
>
)}
+ {getResults.data?.step === 5 && (
+
+ {permissionsResult.isFetching && } Authentication has been received.
+ Checking if all prerequisites are met to connect to your tenants.
+ {permissionsResult.isUninitialized && checkPermissions()}
+
+ )}
+
+ {permissionsResult.data?.Results && (
+ <>
+
+
+ {permissionsResult.data.Results?.Messages && (
+ <>
+ {permissionsResult.data.Results?.Messages?.map((m, idx) => (
+ {m}
+ ))}
+ >
+ )}
+
+
+
+ {permissionsResult.data.Results?.ErrorMessages?.length >= 1 && (
+
+ {permissionsResult.data.Results?.ErrorMessages?.map((m, idx) => (
+ {m}
+ ))}
+
+ )}
+
+ >
+ )}
+
@@ -251,40 +320,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)
+ }
+ }}
+
diff --git a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx
index 8f8ebed14efc..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'
@@ -41,6 +51,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 +65,9 @@ export function SettingsExtensionMappings() {
setNinjaOrgsExtensionconfig({
path: 'api/ExecExtensionMapping?AddMapping=NinjaOrgs',
values: { mappings: originalFormat },
+ }).then(() => {
+ listNinjaOrgsBackend({ path: 'api/ExecExtensionMapping?List=NinjaOrgs' })
+ setMappingValue({})
})
}
@@ -68,7 +84,6 @@ export function SettingsExtensionMappings() {
const onNinjaFieldsSubmit = (values) => {
setNinjaFieldsExtensionconfig({
path: 'api/ExecExtensionMapping?AddMapping=NinjaFields',
-
values: { mappings: values },
})
}
@@ -91,8 +106,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)
}
@@ -230,82 +248,99 @@ 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 ? (
-
- ) : (
-
-
-
- {' '}
-
-
- {extensionNinjaOrgsConfigResult.isFetching && (
-
- )}
- Set Mappings
-
- onNinjaOrgsAutomap()} className="me-2">
- {extensionNinjaOrgsAutomapResult.isFetching && (
-
- )}
- Automap NinjaOne Organizations
-
- >
- }
- >
- {listBackendNinjaOrgsResult.isFetching ? (
-
- ) : (
- {
- 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 && (
-
- )
- }
-
-
- ({
- name: tenant.displayName,
- value: tenant.customerId,
- }))}
- onChange={(e) => {
- setMappingArray(e.value)
- }}
- />
-
-
-
-
-
- ({
- name: client.name,
- value: client.value,
- }))}
- onChange={(e) => setMappingValue(e)}
- placeholder="Select a NinjaOne Organization"
- />
-
-
- //set the new mapping in the array
+
+
+
+ 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}
+ />
+
+ {
+ //set the new mapping in the array
+ if (
+ mappingValue.value !== undefined &&
+ Object.values(ninjaMappingsArray)
+ .map((item) => item.ninjaId)
+ .includes(mappingValue.value) === false
+ ) {
setNinjaMappingsArray([
...ninjaMappingsArray,
{
@@ -446,144 +496,137 @@ export function SettingsExtensionMappings() {
},
])
}
- className={`my-4 circular-button`}
- title={'+'}
+ }}
+ className={`my-4 circular-button`}
+ title={'+'}
+ >
+
+
+
+
+
+ {(extensionNinjaOrgsAutomapResult.isSuccess ||
+ extensionNinjaOrgsAutomapResult.isError) &&
+ !extensionNinjaOrgsAutomapResult.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 && (
-
- )}
- 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'}
-
- )}
-
-
- )
- }}
- />
- )}
-
-
- >
+ {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' && (
+
+
+
+ ),
+ )}
+
+
+
+
+ )
+ }}
+ />
+
))}
-
+
>
)
diff --git a/src/views/cipp/app-settings/SettingsGeneral.jsx b/src/views/cipp/app-settings/SettingsGeneral.jsx
index 98a34210c72b..04446add8ceb 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,50 +212,80 @@ export function SettingsGeneral() {
<>
{permissionsResult.data.Results?.AccessTokenDetails?.Name !== '' && (
<>
- setTokenOffcanvasVisible(true)}>
- Details
-
- setTokenOffcanvasVisible(false)}
- />
+
+
+
+ Authentication User
+ Authentication IP
+ Application
+
+
+
+
+
+ {permissionsResult.data.Results?.AccessTokenDetails?.UserPrincipalName}
+
+ {permissionsResult.data.Results?.AccessTokenDetails?.IPAddress}
+
+
+ Link
+
+
+
+
+
>
)}
-
- {permissionsResult.data.Results?.Messages && (
- <>
- {permissionsResult.data.Results?.Messages?.map((m, idx) => (
- {m}
+
+
+
+ {permissionsResult.data.Results?.Messages && (
+ <>
+ {permissionsResult.data.Results?.Messages?.map((m, idx) => (
+ {m}
+ ))}
+ >
+ )}
+
+
+
+ {permissionsResult.data.Results?.ErrorMessages?.length > 0 ||
+ (permissionsResult.data.Results?.MissingPermissions.length > 0 && (
+
+ <>
+ {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}
- ))}
-
- >
- )}
-
+
+
>
)}
diff --git a/src/views/cipp/app-settings/SettingsMaintenance.jsx b/src/views/cipp/app-settings/SettingsMaintenance.jsx
index d7387f849400..a65add447d5d 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 { CippActionsOffcanvas, ModalService } from 'src/components/utilities'
/**
* Performs maintenance operations on settings.
@@ -24,138 +15,232 @@ 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 = (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: 'Danger Zone',
+ body: Are you sure you want to {actionText}
,
+ onConfirm: () =>
+ resetDurables({
+ path: '/api/ExecDurableFunctions',
+ params: { Action: action },
+ }).then(() => {
+ orchestrators.refetch()
+ durableStats.refetch()
+ }),
+ confirmLabel: 'Reset',
+ cancelLabel: 'Cancel',
})
}
- return (
+
+ 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 = (
<>
- {listBackendResult.isUninitialized && listBackend({ path: 'api/ExecMaintenanceScripts' })}
-
-
-
-
- Maintenance
-
-
- {
- return (
-
- {listBackendResult.isFetching && (
- <>
-
-
-
-
-
- >
- )}
- {!listBackendResult.isFetching && listBackendResult.isSuccess && (
- <>
-
-
-
-
-
-
-
-
-
- Load Script
-
-
-
- >
- )}
-
- )
- }}
- />
-
-
+ handleResetDurables('ResetDurables')}
+ color="danger"
+ className="me-2"
+ >
+ Clear Durable Queues
+
+ handleResetDurables('PurgeOrchestrators')}
+ color="danger"
+ className="me-2"
+ >
+ Purge Orchestrators
+
+ >
+ )
+
+ return (
+
+
+
+ {
+ return queue?.Name
+ })}
+ ChartData={durableStats.data?.Queues?.map((queue) => {
+ return queue?.ApproximateMessageCount
+ })}
+ isFetching={durableStats.isFetching}
+ refreshFunction={() => durableStats.refetch()}
+ />
+
+
+ {
+ return status.Name
+ })}
+ ChartData={durableStats?.data?.Orchestrators?.map((status) => {
+ return status.Count
+ })}
+ isFetching={durableStats.isFetching}
+ 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
-
-
- )}
-
-
- )}
+
+
+
+ ,
+ 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(),
+ },
+ {
+ name: 'Input',
+ selector: (row) => row['Input'],
+ cell: cellGenericFormatter(),
+ },
+ {
+ name: 'Actions',
+ cell: Actions,
+ maxWidth: '100px',
+ },
+ ]}
+ 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()}
+ />
+
- >
+
)
}
diff --git a/src/views/cipp/app-settings/SettingsNotifications.jsx b/src/views/cipp/app-settings/SettingsNotifications.jsx
index 555a1fbdd19d..781d2ac72e6a 100644
--- a/src/views/cipp/app-settings/SettingsNotifications.jsx
+++ b/src/views/cipp/app-settings/SettingsNotifications.jsx
@@ -44,11 +44,20 @@ export function SettingsNotifications() {
generateTestAlert({ text: 'Test Alert', Severity: 'Alert' })}
+ onClick={() =>
+ generateTestAlert({ text: 'Manually Generated Test Alert', Severity: 'Alert' })
+ }
disabled={generateAlertResult.isFetching}
>
- {generateAlertResult.isFetching && }
- {generateAlertResult.isSuccess && }
+ {generateAlertResult.isFetching ? (
+
+ ) : (
+ <>
+ {generateAlertResult.isSuccess && (
+
+ )}
+ >
+ )}
Generate Test Alert
>
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."
/>
+
{
+ 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..e3a44ab7e7cc 100644
--- a/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx
+++ b/src/views/email-exchange/administration/ListTenantAllowBlockList.jsx
@@ -1,92 +1,121 @@
-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 (
+ }
title="Tenant Allow/Block Lists"
datatable={{
- columns,
- path: '/api/ListTenantAllowBlockList',
+ keyField: 'id',
reportName: `${tenant?.defaultDomainName}-TenantAllowBlockList`,
+ path: '/api/ListTenantAllowBlockList',
+ columns,
params: { TenantFilter: tenant?.defaultDomainName },
}}
/>
diff --git a/src/views/email-exchange/administration/QuarantineList.jsx b/src/views/email-exchange/administration/QuarantineList.jsx
index a97211466431..7453af66b1a7 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,33 @@ 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 },
}}
/>
diff --git a/src/views/email-exchange/connectors/ConnectorList.jsx b/src/views/email-exchange/connectors/ConnectorList.jsx
index 990e1d555199..c18d5eeb0004 100644
--- a/src/views/email-exchange/connectors/ConnectorList.jsx
+++ b/src/views/email-exchange/connectors/ConnectorList.jsx
@@ -151,6 +151,20 @@ 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 },
diff --git a/src/views/email-exchange/rooms/ListRoomLists.jsx b/src/views/email-exchange/rooms/ListRoomLists.jsx
new file mode 100644
index 000000000000..3da41e5c6fd3
--- /dev/null
+++ b/src/views/email-exchange/rooms/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/email-exchange/rooms/ListRooms.jsx b/src/views/email-exchange/rooms/ListRooms.jsx
new file mode 100644
index 000000000000..a94a60fb8b12
--- /dev/null
+++ b/src/views/email-exchange/rooms/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
diff --git a/src/views/email-exchange/tools/MailTest.jsx b/src/views/email-exchange/tools/MailTest.jsx
index 633d351fd489..27b55070f6db 100644
--- a/src/views/email-exchange/tools/MailTest.jsx
+++ b/src/views/email-exchange/tools/MailTest.jsx
@@ -40,22 +40,22 @@ const MailTest = () => {
},
{
name: 'SPF',
- selector: (row) => row?.AuthResult.filter((x) => x?.Name === 'spf')[0]?.Status == 'pass',
+ selector: (row) => row?.AuthResult?.find((x) => x?.Name === 'spf')?.Status == 'pass',
cell: cellBooleanFormatter(),
},
{
name: 'DKIM',
- selector: (row) => row?.AuthResult.filter((x) => x?.Name === 'dkim')[0]?.Status == 'pass',
+ selector: (row) => row?.AuthResult?.find((x) => x?.Name === 'dkim')?.Status == 'pass',
cell: cellBooleanFormatter(),
},
{
name: 'DMARC',
- selector: (row) => row?.AuthResult.filter((x) => x?.Name === 'dmarc')[0]?.Status == 'pass',
+ selector: (row) => row?.AuthResult?.find((x) => x?.Name === 'dmarc')?.Status == 'pass',
cell: cellBooleanFormatter(),
},
{
name: 'Comp Auth',
- selector: (row) => row?.AuthResult.filter((x) => x?.Name === 'compauth')[0]?.Status == 'pass',
+ selector: (row) => row?.AuthResult?.find((x) => x?.Name === 'compauth')?.Status == 'pass',
cell: cellBooleanFormatter(),
},
{
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 },
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}
diff --git a/src/views/home/Home.jsx b/src/views/home/Home.jsx
index d5dfafb0e552..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 { useMediaPredicate } from 'react-media-hook'
+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 (
<>
@@ -333,10 +379,17 @@ const TenantDashboard = () => {
options={{
plugins: {
legend: {
- position: 'bottom',
+ position: 'left',
labels: {
color: getStyle('--cui-body-color'),
},
+ onClick: userChartLegendClickHandler,
+ onHover: (event) => {
+ event.native.target.style.cursor = 'pointer'
+ },
+ onLeave: (event) => {
+ event.native.target.style.cursor = 'default'
+ },
},
},
}}
@@ -422,14 +475,20 @@ const TenantDashboard = () => {
{
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}
+
))}
diff --git a/src/views/identity/administration/Users.jsx b/src/views/identity/administration/Users.jsx
index dc3b5243815b..2d0a4aa9ac49 100644
--- a/src/views/identity/administration/Users.jsx
+++ b/src/views/identity/administration/Users.jsx
@@ -480,6 +480,7 @@ const Users = (row) => {
'id,accountEnabled,businessPhones,city,createdDateTime,companyName,country,department,displayName,faxNumber,givenName,isResourceAccount,jobTitle,mail,mailNickname,mobilePhone,onPremisesDistinguishedName,officeLocation,onPremisesLastSyncDateTime,otherMails,postalCode,preferredDataLocation,preferredLanguage,proxyAddresses,showInAddressList,state,streetAddress,surname,usageLocation,userPrincipalName,userType,assignedLicenses,onPremisesSyncEnabled',
$count: true,
$orderby: 'displayName',
+ $top: 999,
},
tableProps: {
keyField: 'id',
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,
diff --git a/src/views/tenant/administration/AlertWizard.jsx b/src/views/tenant/administration/AlertWizard.jsx
index c2e920354e15..2c3bf20bf0cf 100644
--- a/src/views/tenant/administration/AlertWizard.jsx
+++ b/src/views/tenant/administration/AlertWizard.jsx
@@ -1,346 +1,444 @@
-import React from 'react'
-import { CCol, CRow, CForm, CListGroup, CListGroupItem, CCallout, CSpinner } from '@coreui/react'
-import { Field, FormSpy } from 'react-final-form'
-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 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'
+import { CippPage } from 'src/components/layout'
+import { TenantSelector, TenantSelectorMultiple } from 'src/components/utilities'
+import {
+ Condition,
+ RFFCFormInput,
+ RFFCFormSwitch,
+ RFFSelectSearch,
+} from 'src/components/forms/RFFComponents'
+import { useListTenantQuery } from 'src/store/api/tenants'
import { useLazyGenericPostRequestQuery } from 'src/store/api/app'
-import countryList from 'src/data/countryList.json'
+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 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)
+ 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)
+
+ const onSubmitAudit = (values) => {
+ genericPostRequest({ path: '/api/addAlert', values }).then((res) => {})
+ }
-const Error = ({ name }) => (
-
- touched && error ? (
-
-
- {error}
-
- ) : null
+ const onSubmitScript = (values) => {
+ //get current time as startDate, to the closest 15 minutes in the future
+ const startDate = new Date()
+ 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}`,
+ 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/AddScheduledItem?hidden=true', values: shippedValues }).then(
+ (res) => {},
+ )
+ }
-Error.propTypes = {
- name: PropTypes.string.isRequired,
-}
+ const initialValues = {
+ ...tenant[0],
+ ...currentFormState?.values,
+ ...recommendedRecurrence,
+ }
+ const [auditFormState, setAuditFormState] = useState()
-const requiredArray = (value) => (value && value.length !== 0 ? undefined : 'Required')
+ const initialValuesAudit = {
+ tenantFilter: [...selectedTenant],
+ ...auditFormState,
+ }
+ 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 AlertWizard = () => {
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
+ const presetValues = auditLogTemplates
- 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 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 formValues = {}
+ 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 (
-
-
-
- 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.
-
-
-
-
-
-
-
-
-
-
-
-
+ const setAuditForm = (e) => {
+ const preset = presetValues.find((p) => p.value === e.value)
+ setAuditFormState(preset.template)
+ 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' },
+ ]
-
-
-
-
- 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.
-
-
-
-
+ return (
+
+ {isFetching && }
+ {!isFetching && (
+ <>
+
+
+ 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
+
-
-
-
-
-
- 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}
- })}
-
- )}
-
-
-
+ {alertType === 'audit' && (
+ <>
+
+
+
+ Select the tenants you want to include in this Alert.
+ setSelectedTenant(e)}
+ AllTenants={true}
+ valueisDomain={true}
+ />
+
+
+
+ {
+ return (
+
+
+
+
+ {postResults.isFetching && } Save Alert
+
+ }
+ >
+
+
+ setAuditForm(e)}
+ />
+
+
+
+
+
+
+
+ {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={'+'}
+ >
+
+
+ )}
+
+
+
+
+
+
+ {postResults.isSuccess && (
+
+ {postResults.data.Results}
+
+ )}
+
+
+
+
+
+ )
+ }}
+ />
+ >
+ )}
+ {alertType === 'script' && (
+ <>
+
+
+
+ Select the tenants you want to include in this Alert.
+
+
+
+
+
+
+
+ Save Alert
+ {postResults.isFetching && (
+
+ )}
+
+ }
+ >
+ {
+ return (
+
+
+
+ ({
+ value: cmd,
+ name: cmd.label,
+ }))}
+ name="command"
+ placeholder={'Select a command'}
+ label="What alerting script should run"
+ validate={required}
+ />
+
+
+
+
+
+
+ {(props) => {
+ return (
+
+ )
+ }}
+
+
+
+
+
+
+ setCurrentFormState(formvalues)}
+ />
+
+
+
+
+
+ Receive Alert via:
+
+
+
+
+
+ {postResults.isSuccess && (
+
+ {postResults.data.Results}
+
+ )}
+
+ )
+ }}
+ />
+
+
+
+ >
+ )}
+ >
+ )}
+
)
}
diff --git a/src/views/tenant/administration/GraphExplorer.jsx b/src/views/tenant/administration/GraphExplorer.jsx
index bad378c27d3a..3d6950c598d4 100644
--- a/src/views/tenant/administration/GraphExplorer.jsx
+++ b/src/views/tenant/administration/GraphExplorer.jsx
@@ -75,7 +75,38 @@ const GraphExplorer = () => {
}, [])
if (graphrequest.isSuccess) {
- if (graphrequest.data?.Results?.length > 0) {
+ if (
+ graphrequest.data?.Metadata?.Parameters?.$select !== undefined &&
+ graphrequest.data?.Metadata?.Parameters?.$select !== '' &&
+ graphrequest.data?.Metadata?.Parameters?.$select !== null
+ ) {
+ //set columns
+ if (graphrequest.data?.Metadata?.TenantFilter === 'AllTenants') {
+ QueryColumns.data.push({
+ name: 'Tenant',
+ selector: (row) => row['Tenant'],
+ sortable: true,
+ exportSelector: 'Tenant',
+ cell: cellGenericFormatter(),
+ })
+ QueryColumns.data.push({
+ name: 'CippStatus',
+ selector: (row) => row['CippStatus'],
+ sortable: true,
+ exportSelector: 'CippStatus',
+ cell: cellGenericFormatter(),
+ })
+ }
+ graphrequest.data?.Metadata?.Parameters?.$select.split(',')?.map((value) =>
+ QueryColumns.data.push({
+ name: value,
+ selector: (row) => row[`${value.toString()}`],
+ sortable: true,
+ exportSelector: value,
+ cell: cellGenericFormatter(),
+ }),
+ )
+ } else if (graphrequest.data?.Results?.length > 0) {
//set columns
Object.keys(graphrequest.data?.Results[0]).map((value) =>
QueryColumns.data.push({
@@ -121,7 +152,7 @@ const GraphExplorer = () => {
{
name: 'All users with email addresses',
id: '6164e239-0c9a-4a27-9049-6250bf65a3e3',
- params: { endpoint: '/users', $select: 'userprincipalname,mail,proxyAddresses', $filter: '' },
+ params: { endpoint: '/users', $select: 'userPrincipalName,mail,proxyAddresses', $filter: '' },
isBuiltin: true,
},
{
@@ -248,6 +279,9 @@ const GraphExplorer = () => {
if (params?.$select) {
select = params.$select.map((p) => p.value).join(',')
}
+ if (params?.name) {
+ params.QueueNameOverride = 'Graph Explorer - ' + params.name
+ }
execGraphRequest({
path: 'api/ListGraphRequest',
params: {
@@ -505,6 +539,13 @@ const GraphExplorer = () => {
label="Reverse Tenant Lookup"
/>
+
+
{
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: 'Repeats every',
+ selector: (row) => row['RepeatsEvery'],
+ sortable: true,
+ cell: (row) => CellTip(row['RepeatsEvery']),
+ exportSelector: 'RepeatsEvery',
+ },
+ {
+ 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 && }
-
-
- Tenant
- {(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}`,
}}
/>
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,
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,
diff --git a/src/views/tenant/administration/SecureScore.jsx b/src/views/tenant/administration/SecureScore.jsx
index 2af727c7b9dc..76c77d584296 100644
--- a/src/views/tenant/administration/SecureScore.jsx
+++ b/src/views/tenant/administration/SecureScore.jsx
@@ -26,6 +26,7 @@ import { useNavigate } from 'react-router-dom'
import { ModalService } from 'src/components/utilities'
import { CellTip, cellGenericFormatter } from 'src/components/tables/CellGenericFormat'
import { CippCallout } from 'src/components/layout'
+import CippPrettyCard from 'src/components/contentcards/CippPrettyCard'
const SecureScore = () => {
const textRef = useRef()
@@ -220,93 +221,60 @@ const SecureScore = () => {
-
-
- Current Score
-
-
-
- {isFetching && }
- {translateState && (
- <>
-
- {Math.round(
- (translateData?.currentScore / translateData?.maxScore) * 100 * 10,
- ) / 10}
- %
-
-
- {translateData?.currentScore} of {translateData?.maxScore} points
-
- >
- )}
-
-
-
+
-
-
- Compared Score (Similiar sized business)
-
-
-
- {isFetching && }
- {translateState && (
- <>
-
- {
- //calculate percentage, round to 1 dec.
- Math.round(
- (translateData?.averageComparativeScores[1]?.averageScore /
- translateData?.maxScore) *
- 100 *
- 10,
- ) / 10
- }
- %
-
-
- {translateData?.averageComparativeScores[1]?.averageScore} of{' '}
- {translateData?.maxScore} points
-
- >
- )}
-
-
-
+
-
-
- Compared Score (All businesses)
-
-
-
- {isFetching && }
- {translateState && (
- <>
-
- {
- //calculate percentage, round to 1 dec.
- Math.round(
- (translateData?.averageComparativeScores[0]?.averageScore /
- translateData?.maxScore) *
- 100 *
- 10,
- ) / 10
- }
- %
-
-
- {translateData?.averageComparativeScores[0]?.averageScore} of{' '}
- {translateData?.maxScore} points
-
- >
- )}
-
-
-
+
diff --git a/src/views/tenant/administration/TenantLookup.jsx b/src/views/tenant/administration/TenantLookup.jsx
index abb95f701571..ced62911ae8d 100644
--- a/src/views/tenant/administration/TenantLookup.jsx
+++ b/src/views/tenant/administration/TenantLookup.jsx
@@ -122,25 +122,27 @@ 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
{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'}
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..ebbab2a8e178 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,20 @@ const TenantOnboardingWizard = () => {
Tenant Onboarding Options
+ Standards
+
+ 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.
+
@@ -419,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
new file mode 100644
index 000000000000..9147caebbf63
--- /dev/null
+++ b/src/views/tenant/administration/onboarding/RelationshipOnboarding.jsx
@@ -0,0 +1,212 @@
+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,
+ standardsExcludeAllTenants,
+}) => {
+ const [getOnboardingStatus, onboardingStatus] = useLazyGenericPostRequestQuery()
+
+ useInterval(
+ async () => {
+ if (onboardingStatus.data?.Status == 'running' || onboardingStatus.data?.Status == 'queued') {
+ getOnboardingStatus({
+ path: `/api/ExecOnboardTenant`,
+ values: { id: relationship.id },
+ })
+ }
+ },
+ 5000,
+ onboardingStatus.data,
+ )
+ console.log(standardsExcludeAllTenants)
+
+ 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,
+ standardsExcludeAllTenants,
+ },
+ })}
+ {onboardingStatus.isSuccess && (
+ <>
+ {onboardingStatus.data?.Status != 'queued' && (
+
+ getOnboardingStatus({
+ path: '/api/ExecOnboardTenant?Retry=True',
+ values: {
+ id: relationship.id,
+ gdapRoles,
+ autoMapRoles,
+ addMissingGroups,
+ standardsExcludeAllTenants,
+ },
+ })
+ }
+ 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,
+ standardsExcludeAllTenants: PropTypes.bool,
+}
+
+export default RelationshipOnboarding
diff --git a/src/views/tenant/standards/ListAppliedStandards.jsx b/src/views/tenant/standards/ListAppliedStandards.jsx
index b5c8bc3c8174..484ec3862a36 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'
@@ -73,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({
@@ -258,12 +262,20 @@ 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({
path: 'api/listStandards',
})
+ const {
+ data: consolidatedStandards = [],
+ isSuccess: consolidatedSuccess,
+ refetch: refetchConsolidated,
+ } = useGenericGetRequestQuery({
+ path: 'api/listStandards',
+ params: { TenantFilter: tenantDomain, ShowConsolidated: true },
+ })
const {
data: listStandardResults = [],
@@ -287,6 +299,9 @@ const ApplyNewStandard = () => {
genericPostRequest({
path: '/api/AddStandardsDeploy',
values: { ...values.standards, tenant: tenantDomain },
+ }).then(() => {
+ refetchStandards()
+ refetchConsolidated()
})
}
const [intuneGetRequest, intuneTemplates] = useLazyGenericGetRequestQuery()
@@ -298,16 +313,20 @@ const ApplyNewStandard = () => {
(tenant) => tenant.displayName === 'AllTenants',
)
- function getLabel(item, type) {
+ 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]) {
- return ''
+ if (
+ !value ||
+ !value[type] ||
+ listStandardResults[0]?.standards?.OverrideAllTenants?.remediate === true
+ ) {
+ return false
}
- return `* Enabled via All Tenants`
+ return true
}
const groupedStandards = allStandardsList.reduce((acc, obj) => {
@@ -316,29 +335,38 @@ const ApplyNewStandard = () => {
return acc
}, {})
- // 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++
- }
- })
- return count
- }
-
- // Assuming listStandardResults[0] contains your JSON object
- const enabledStandards = listStandardResults[0] ? listStandardResults[0].standards : {}
- const enabledAlertsCount = countEnabledStandards(enabledStandards, 'alert')
- const enabledRemediationsCount = countEnabledStandards(enabledStandards, 'remediate')
- 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]++
+ }
+ })
+ }
+ })
+ setEnabledAlertsCount(enabledCounts['alert'])
+ setEnabledRemediationsCount(enabledCounts['remediate'])
+ setEnabledWarningsCount(enabledCounts['report'])
+ }
+ }, [
+ consolidatedStandards,
+ consolidatedSuccess,
+ setEnabledAlertsCount,
+ setEnabledRemediationsCount,
+ setEnabledWarningsCount,
+ ])
+
return (
<>
@@ -367,624 +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={`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 (
-
-
-
- 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"
- />
-
-
- {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
-
-
-
-
- )}
- {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,
- }))}
- />
- )}
- >
- ))}
-
-
- ))}
-
-
- ))}
-
- 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
+
+ >
+ )
+ }}
+
+
+
+
+
+ )
+ }}
+ />
+ )}
+
>
)
diff --git a/version_latest.txt b/version_latest.txt
index b7c75422bc1d..42cdd0b540f9 100644
--- a/version_latest.txt
+++ b/version_latest.txt
@@ -1 +1 @@
-5.6.1
+5.7.0