diff --git a/.gitignore b/.gitignore
index 0c9f36fe2e8a..1f85272ad618 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,18 +1,21 @@
-# See https://help.github.com/ignore-files/ for more about ignoring files.
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
-/node_modules
-
+node_modules
+.pnp
+.pnp.js
+build
# testing
-/coverage
+coverage
# production
-/build
+.next
+out
# misc
-.eslintcache
.DS_Store
-.idea
+.eslintcache
+.env
.env.local
.env.development.local
.env.test.local
@@ -21,5 +24,6 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
-__*
-.next/*
+
+# vscode debug logs
+debug.log
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
deleted file mode 100644
index c21abba6989f..000000000000
--- a/.vscode/extensions.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "recommendations": [
- "github.vscode-codeql",
- "dbaeumer.vscode-eslint",
- "eg2.vscode-npm-script",
- "christian-kohler.npm-intellisense",
- "esbenp.prettier-vscode",
- "stylelint.vscode-stylelint",
- "editorconfig.editorconfig"
- ]
-}
diff --git a/Tools/Start-CippDevEmulators.ps1 b/Tools/Start-CippDevEmulators.ps1
index b4f6ca696ffe..882579f1bdc4 100644
--- a/Tools/Start-CippDevEmulators.ps1
+++ b/Tools/Start-CippDevEmulators.ps1
@@ -1,4 +1,12 @@
-Write-Host "Starting CIPP Dev Emulators"
+Write-Host 'Starting CIPP Dev Emulators'
+Get-Process node -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue
$Path = (Get-Item $PSScriptRoot).Parent.Parent.FullName
-wt --title CIPP`; new-tab --title 'Azurite' -d $Path pwsh -c azurite`; new-tab --title 'FunctionApp' -d $Path\CIPP-API pwsh -c func start`; new-tab --title 'CIPP Frontend' -d $Path\CIPP pwsh -c npm run start`; new-tab --title 'SWA' -d $Path\CIPP pwsh -c npm run start-swa
+
+$Process = Read-Host -Prompt 'Start Process Function (y/N)?'
+
+if ($Process -eq 'y') {
+ wt --title CIPP`; new-tab --title 'Azurite' -d $Path pwsh -c azurite`; new-tab --title 'FunctionApp' -d $Path\CIPP-API pwsh -c func start`; new-tab --title 'CIPP Frontend' -d $Path\CIPP pwsh -c npm run dev`; new-tab --title 'SWA' -d $Path\CIPP pwsh -c npm run start-swa`; new-tab --title 'CIPP-API-Processor' -d $Path\CIPP-API-Processor pwsh -c func start --port 7072
+} else {
+ wt --title CIPP`; new-tab --title 'Azurite' -d $Path pwsh -c azurite`; new-tab --title 'FunctionApp' -d $Path\CIPP-API pwsh -c func start`; new-tab --title 'CIPP Frontend' -d $Path\CIPP pwsh -c npm run dev`; new-tab --title 'SWA' -d $Path\CIPP pwsh -c npm run start-swa
+}
diff --git a/deployment/AzureDeploymentTemplate.json b/deployment/AzureDeploymentTemplate.json
index 856221dd1122..91ce52c678a7 100644
--- a/deployment/AzureDeploymentTemplate.json
+++ b/deployment/AzureDeploymentTemplate.json
@@ -176,7 +176,7 @@
"name": "[variables('funcStorageName')]",
"location": "[resourceGroup().location]",
"tags": {
- "displayName": "funStorageName"
+ "displayName": "funcStorageName"
},
"sku": {
"name": "Standard_LRS"
diff --git a/deployment/AzureDeploymentTemplate_regionoptions.json b/deployment/AzureDeploymentTemplate_regionoptions.json
index 7c87332aab2a..7e23726404c2 100644
--- a/deployment/AzureDeploymentTemplate_regionoptions.json
+++ b/deployment/AzureDeploymentTemplate_regionoptions.json
@@ -6,7 +6,7 @@
"defaultValue": "CIPP",
"type": "string",
"metadata": {
- "description": "Name use as base-template to named the resources deployed in Azure."
+ "description": "Name used as base-template to name the resources deployed in Azure."
}
},
"GithubRepository": {
@@ -20,7 +20,7 @@
"defaultValue": "GeneratedPassword",
"type": "string",
"metadata": {
- "description": "Your Github Repository token (see https://docs.microsoft.com/en-us/azure/static-web-apps/publish-azure-resource-manager?tabs=azure-cli#create-a-github-personal-access-token"
+ "description": "Your Github Repository token (see https://docs.microsoft.com/en-us/azure/static-web-apps/publish-azure-resource-manager?tabs=azure-cli#create-a-github-personal-access-token)"
}
}
},
@@ -176,7 +176,7 @@
"name": "[variables('funcStorageName')]",
"location": "[resourceGroup().location]",
"tags": {
- "displayName": "funStorageName"
+ "displayName": "funcStorageName"
},
"sku": {
"name": "Standard_LRS"
@@ -220,7 +220,7 @@
"buildProperties": {
"appLocation": "/",
"apiLocation": "",
- "appArtifactLocation": ""
+ "outputLocation": "/out"
}
},
"sku": {
diff --git a/deployment/DevAzureDeploymentTemplate.json b/deployment/DevAzureDeploymentTemplate.json
index 8beefadd450c..5e6077beab41 100644
--- a/deployment/DevAzureDeploymentTemplate.json
+++ b/deployment/DevAzureDeploymentTemplate.json
@@ -6,7 +6,7 @@
"defaultValue": "CIPPDev",
"type": "string",
"metadata": {
- "description": "Name use as base-template to named the resources deployed in Azure."
+ "description": "Name used as base-template to name the resources deployed in Azure."
}
},
"TenantID": {
@@ -48,7 +48,7 @@
"defaultValue": "GeneratedPassword",
"type": "string",
"metadata": {
- "description": "Your Github Repository token (see https://docs.microsoft.com/en-us/azure/static-web-apps/publish-azure-resource-manager?tabs=azure-cli#create-a-github-personal-access-token"
+ "description": "Your Github Repository token (see https://docs.microsoft.com/en-us/azure/static-web-apps/publish-azure-resource-manager?tabs=azure-cli#create-a-github-personal-access-token)"
}
},
"GithubAPIRepository": {
@@ -250,7 +250,7 @@
"name": "[variables('funcStorageName')]",
"location": "[resourceGroup().location]",
"tags": {
- "displayName": "funStorageName"
+ "displayName": "funcStorageName"
},
"sku": {
"name": "Standard_LRS"
diff --git a/deployment/DevAzureDeploymentTemplate_regionoptions.json b/deployment/DevAzureDeploymentTemplate_regionoptions.json
index 52eb733412fc..f17135c01057 100644
--- a/deployment/DevAzureDeploymentTemplate_regionoptions.json
+++ b/deployment/DevAzureDeploymentTemplate_regionoptions.json
@@ -6,7 +6,7 @@
"defaultValue": "CIPP",
"type": "string",
"metadata": {
- "description": "Name use as base-template to named the resources deployed in Azure."
+ "description": "Name used as base-template to name the resources deployed in Azure."
}
},
"TenantID": {
@@ -48,7 +48,7 @@
"defaultValue": "GeneratedPassword",
"type": "string",
"metadata": {
- "description": "Your Github Repository token (see https://docs.microsoft.com/en-us/azure/static-web-apps/publish-azure-resource-manager?tabs=azure-cli#create-a-github-personal-access-token"
+ "description": "Your Github Repository token (see https://docs.microsoft.com/en-us/azure/static-web-apps/publish-azure-resource-manager?tabs=azure-cli#create-a-github-personal-access-token)"
}
},
"GithubAPIRepository": {
diff --git a/package.json b/package.json
index a8a975f0c44c..6c2c57ba925d 100644
--- a/package.json
+++ b/package.json
@@ -1,130 +1,110 @@
{
"name": "cipp",
- "version": "6.4.1",
- "description": "The CyberDrain Improved Partner Portal is a portal to help manage administration for Microsoft Partners.",
+ "version": "7.0.0",
+ "author": "CIPP Contributors",
"homepage": "https://cipp.app/",
"bugs": {
"url": "https://github.com/KelvinTegelaar/CIPP/issues"
},
+ "engines": {
+ "node": "^18.17.0"
+ },
"repository": {
"type": "git",
"url": "git@github.com:KelvinTegelaar/CIPP.git"
},
- "type": "module",
- "license": "AGPL-3.0",
- "author": "CIPP Contributors",
"scripts": {
- "prebuild": "node Generate-Import-Map.js",
- "build": "echo react-scripts build && vite build",
- "changelog": "auto-changelog --starting-version 3.0.0 --commit-limit false --hide-credit",
- "lint": "eslint \"src/**/*.js\"",
- "start": "vite",
- "start-swa": "swa start --swa-config-location .vscode http://127.0.0.1:3000 --api-location http://127.0.0.1:7071",
- "prepare": "husky install",
- "preview": "vite preview"
- },
- "config": {
- "coreui_library_short_version": "4.1"
+ "dev": "next -H 127.0.0.1",
+ "build": "next build && next export",
+ "start": "next start",
+ "export": "next export",
+ "lint": "next lint",
+ "lint-fix": "next lint --fix",
+ "start-swa": "swa start --swa-config-location .vscode http://127.0.0.1:3000 --api-location http://127.0.0.1:7071 --verbose=silly"
},
"dependencies": {
- "@coreui/chartjs": "^3.0.0",
- "@coreui/coreui": "^4.3.0",
- "@coreui/react": "^4.11.0",
- "@coreui/react-chartjs": "^2.1.3",
- "@coreui/utils": "^1.3.1",
- "@fortawesome/fontawesome-svg-core": "^6.5.1",
- "@fortawesome/free-brands-svg-icons": "^6.5.1",
- "@fortawesome/free-regular-svg-icons": "^6.5.1",
- "@fortawesome/free-solid-svg-icons": "^6.5.1",
- "@fortawesome/react-fontawesome": "^0.2.0",
- "@monaco-editor/react": "^4.5.2",
- "@popperjs/core": "^2.10.2",
- "@reduxjs/toolkit": "^1.9.7",
- "@rjsf/bootstrap-4": "^5.12.1",
- "@rjsf/core": "^5.12.1",
- "@rjsf/utils": "^5.12.1",
- "@rjsf/validator-ajv8": "^5.12.1",
- "@uiw/react-json-view": "^2.0.0-alpha.23",
- "axios": "^1.6.2",
- "buffer": "^6.0.3",
- "chart.js": "^3.5.1",
- "classnames": "^2.3.1",
- "core-js": "^3.18.3",
- "dompurify": "^3.1.6",
- "eml-parse-js": "^1.1.14",
- "enzyme": "^3.11.0",
- "final-form": "^4.20.4",
- "final-form-arrays": "^3.1.0",
- "fuse.js": "^7.0.0",
- "fuzzysort": "^1.1.4",
- "javascript-time-ago": "^2.5.9",
- "jspdf": "^2.4.0",
- "jspdf-autotable": "^3.5.23",
- "lodash-es": "^4.17.21",
- "moment": "^2.29.1",
- "prop-types": "^15.7.2",
- "react": "^18.2.0",
- "react-app-polyfill": "^2.0.0",
- "react-bootstrap": "^1.6.5",
- "react-circular-progressbar": "^2.1.0",
+ "@emotion/cache": "11.10.5",
+ "@emotion/react": "11.13.3",
+ "@emotion/server": "11.10.0",
+ "@emotion/styled": "11.13.0",
+ "@heroicons/react": "2.0.15",
+ "@monaco-editor/react": "^4.6.0",
+ "@mui/icons-material": "6.1.6",
+ "@mui/lab": "6.0.0-beta.14",
+ "@mui/material": "6.1.6",
+ "@mui/system": "6.1.6",
+ "@mui/x-date-pickers": "7.22.1",
+ "@musement/iso-duration": "^1.0.0",
+ "@react-pdf/renderer": "3.1.2",
+ "@reduxjs/toolkit": "1.9.2",
+ "@tanstack/react-query": "^5.51.11",
+ "@tanstack/react-query-devtools": "^5.51.11",
+ "@tanstack/react-table": "^8.19.2",
+ "@tiptap/core": "^2.9.1",
+ "@tiptap/extension-heading": "^2.9.1",
+ "@tiptap/extension-image": "^2.9.1",
+ "@tiptap/extension-table": "^2.9.1",
+ "@tiptap/pm": "^2.9.1",
+ "@tiptap/react": "^2.9.1",
+ "@tiptap/starter-kit": "^2.9.1",
+ "@uiw/react-json-view": "^2.0.0-alpha.30",
+ "apexcharts": "3.36.3",
+ "axios": "^1.7.2",
+ "date-fns": "2.29.3",
+ "eml-parse-js": "^1.1.15",
+ "export-to-csv": "^1.3.0",
+ "formik": "2.2.9",
+ "gray-matter": "4.0.3",
+ "i18next": "22.4.9",
+ "javascript-time-ago": "^2.5.11",
+ "jspdf": "^2.5.1",
+ "jspdf-autotable": "^3.8.2",
+ "leaflet": "^1.9.4",
+ "leaflet-defaulticon-compatibility": "^0.1.2",
+ "leaflet.markercluster": "^1.5.3",
+ "lodash.isequal": "4.5.0",
+ "material-react-table": "^3.0.1",
+ "monaco-editor": "^0.52.0",
+ "mui-tiptap": "^1.14.0",
+ "next": "^13.5.6",
+ "nprogress": "0.2.0",
+ "numeral": "2.0.6",
+ "prop-types": "15.8.1",
+ "react": "18.2.0",
+ "react-apexcharts": "1.4.0",
+ "react-beautiful-dnd": "13.1.1",
"react-copy-to-clipboard": "^5.1.0",
- "react-data-table-component": "^7.4.5",
- "react-datepicker": "^4.10.0",
- "react-dom": "^18.2.0",
- "react-dropzone": "^14.2.3",
- "react-final-form": "^6.5.9",
- "react-final-form-arrays": "^3.1.4",
- "react-final-form-listeners": "^1.0.3",
- "react-helmet-async": "^1.3.0",
- "react-hotkeys-hook": "^3.4.4",
+ "react-dom": "18.2.0",
+ "react-dropzone": "14.2.3",
+ "react-error-boundary": "^4.0.13",
+ "react-grid-layout": "^1.5.0",
+ "react-hook-form": "^7.53.0",
+ "react-hot-toast": "2.4.0",
"react-html-parser": "^2.0.2",
- "react-loading-skeleton": "^3.1.0",
- "react-masonry-component": "^6.3.0",
- "react-media-hook": "^0.4.9",
- "react-papaparse": "^3.18.2",
- "react-redux": "^7.2.5",
- "react-router-dom": "^6.1.1",
- "react-select": "^5.3.0",
- "react-select-search": "^3.0.8",
- "react-syntax-highlighter": "^15.4.5",
- "react-time-ago": "^7.2.1",
- "redux": "4.1.1",
+ "react-i18next": "12.1.4",
+ "react-leaflet": "4.2.1",
+ "react-leaflet-markercluster": "^4.2.1",
+ "react-markdown": "8.0.5",
+ "react-media-hook": "^0.5.0",
+ "react-papaparse": "^4.4.0",
+ "react-quill": "^0.0.2",
+ "react-redux": "8.0.5",
+ "react-syntax-highlighter": "^15.6.1",
+ "react-time-ago": "^7.3.3",
+ "react-window": "^1.8.10",
+ "redux": "4.2.1",
+ "redux-devtools-extension": "2.13.9",
"redux-persist": "^6.0.0",
- "simplebar-react": "^2.3.6",
- "source-map-loader": "^3.0.0",
- "styled-components": "^5.3.11"
+ "redux-thunk": "2.4.2",
+ "simplebar": "6.2.0",
+ "simplebar-react": "3.2.0",
+ "stylis-plugin-rtl": "2.1.1",
+ "typescript": "4.9.4",
+ "yup": "0.32.11"
},
"devDependencies": {
- "@types/react": "^18.2.39",
- "@types/react-helmet": "^6.1.5",
- "@vitejs/plugin-react": "^4.2.1",
- "auto-changelog": "~2.3.0",
- "browserslist-to-esbuild": "^1.2.0",
- "eslint": "^8.54.0",
- "eslint-config-prettier": "^8.3.0",
- "eslint-import-resolver-custom-alias": "^1.3.2",
- "eslint-plugin-import": "^2.29.0",
- "eslint-plugin-prettier": "^4.0.0",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "eslint-plugin-react-refresh": "^0.4.4",
- "husky": "^7.0.4",
- "postcss-scss": "^4.0.3",
- "prettier": "2.4.1",
- "redux-immutable-state-invariant": "^2.1.0",
- "sass": "^1.64.2",
- "stylelint": "^14.3.0",
- "stylelint-config-sass-guidelines": "^9.0.1",
- "stylelint-order": "^5.0.0",
- "vite": "^5.0.6",
- "vite-plugin-eslint": "^1.8.1"
- },
- "engines": {
- "node": "20.17.0",
- "npm": ">=8.3.0"
- },
- "overrides": {
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "@svgr/webpack": "6.5.1",
+ "eslint": "8.32.0",
+ "eslint-config-next": "13.1.6"
}
}
diff --git a/public/img/datto.png b/public/img/datto.png
deleted file mode 100644
index b0fad6f50233..000000000000
Binary files a/public/img/datto.png and /dev/null differ
diff --git a/public/version_latest.txt b/public/version_latest.txt
index 4c77920fd2c5..5e39348ef037 100644
--- a/public/version_latest.txt
+++ b/public/version_latest.txt
@@ -1 +1 @@
-6.4.1
+99.99.99
\ No newline at end of file
diff --git a/src/components/CippComponents/CippDropzone.jsx b/src/components/CippComponents/CippDropzone.jsx
index e42ab066ae6f..6e400ef31e2c 100644
--- a/src/components/CippComponents/CippDropzone.jsx
+++ b/src/components/CippComponents/CippDropzone.jsx
@@ -1,37 +1,39 @@
-import React, { useCallback, useMemo, useState } from 'react'
-import PropTypes from 'prop-types'
-import { CippContentCard } from 'src/components/layout'
-import { useDropzone } from 'react-dropzone'
-import styled from 'styled-components'
-import { useMediaPredicate } from 'react-media-hook'
-import { useSelector } from 'react-redux'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import React, { useCallback, useMemo, useState } from "react";
+import PropTypes from "prop-types";
+//import { CippContentCard } from 'src/components/layout'
+import { useDropzone } from "react-dropzone";
+import { styled } from "@mui/material/styles";
+import { useMediaPredicate } from "react-media-hook";
+//import { useSelector } from "react-redux";
+//import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
const getColor = (props) => {
if (props.isDragAccept) {
- return '#00e676'
+ return "#00e676";
}
if (props.isDragReject) {
- return '#ff1744'
+ return "#ff1744";
}
if (props.isFocused) {
- return '#2196f3'
+ return "#2196f3";
}
- return '#eeeeee'
-}
+ return "#eeeeee";
+};
const BackgroundColor = () => {
- const currentTheme = useSelector((state) => state.app.currentTheme)
- const preferredTheme = useMediaPredicate('(prefers-color-scheme: dark)') ? 'impact' : 'cyberdrain'
+ const currentTheme = useSelector((state) => state.app.currentTheme);
+ const preferredTheme = useMediaPredicate("(prefers-color-scheme: dark)")
+ ? "impact"
+ : "cyberdrain";
const isDark =
- currentTheme === 'impact' || (currentTheme === 'default' && preferredTheme === 'impact')
+ currentTheme === "impact" || (currentTheme === "default" && preferredTheme === "impact");
if (isDark) {
- return '#333'
+ return "#333";
} else {
- return '#fafafa'
+ return "#fafafa";
}
-}
+};
const Container = styled.div`
flex: 1;
@@ -47,25 +49,44 @@ const Container = styled.div`
color: #bdbdbd;
outline: none;
transition: border 0.24s ease-in-out;
-`
+`;
-const CippDropzone = ({ title, onDrop, dropMessage, accept, maxFiles = 1, ...props }) => {
+const CippDropzone = ({
+ title,
+ onDrop,
+ dropMessage,
+ accept,
+ maxFiles = 1,
+ returnCard = true,
+ ...props
+}) => {
const { getRootProps, getInputProps, isFocused, isDragAccept, isDragReject } = useDropzone({
onDrop,
accept: accept,
maxFiles: maxFiles,
- })
+ });
return (
-
-
-
-
- {dropMessage}
-
-
-
- )
-}
+ <>
+ {returnCard ? (
+
+
+
+
+ {dropMessage}
+
+
+
+ ) : (
+
+
+
+ {dropMessage}
+
+
+ )}
+ >
+ );
+};
CippDropzone.propTypes = {
title: PropTypes.string,
@@ -73,6 +94,7 @@ CippDropzone.propTypes = {
dropMessage: PropTypes.string,
accept: PropTypes.object,
maxFiles: PropTypes.number,
-}
+ returnCard: PropTypes.bool,
+};
-export default CippDropzone
+export default CippDropzone;
diff --git a/src/components/layout/AppFooter.jsx b/src/components/layout/AppFooter.jsx
deleted file mode 100644
index c720c8f5a35b..000000000000
--- a/src/components/layout/AppFooter.jsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React from 'react'
-import { CFooter, CImage, CLink } from '@coreui/react'
-import { Link } from 'react-router-dom'
-import { useSelector } from 'react-redux'
-import { useMediaPredicate } from 'react-media-hook'
-
-const AppFooter = () => {
- const currentTheme = useSelector((state) => state.app.currentTheme)
- const preferredTheme = useMediaPredicate('(prefers-color-scheme: dark)') ? 'impact' : 'cyberdrain'
- const isDark =
- currentTheme === 'impact' || (currentTheme === 'default' && preferredTheme === 'impact')
-
- const datto = isDark ? '/img/datto.png' : '/img/datto.png'
- const huntress = isDark ? '/img/huntress_teal.png' : '/img/huntress_teal.png'
- const rewst = isDark ? '/img/rewst_dark.png' : '/img/rewst.png'
- const ninjaone = isDark ? '/img/ninjaone_dark.png' : '/img/ninjaone.png'
- const augmentt = isDark ? '/img/augmentt-dark.png' : '/img/augmentt-light.png'
-
- return (
-
-
-
- This application is sponsored by
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- License
-
-
- )
-}
-
-export default React.memo(AppFooter)
diff --git a/src/components/tables/CippDatatable.jsx b/src/components/tables/CippDatatable.jsx
deleted file mode 100644
index 125eeda3e00a..000000000000
--- a/src/components/tables/CippDatatable.jsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import React from 'react'
-import { useListDatatableQuery } from 'src/store/api/datatable'
-import PropTypes from 'prop-types'
-import { CippTable } from 'src/components/tables'
-import { CippTablePropTypes } from 'src/components/tables/CippTable'
-import { CCallout } from '@coreui/react'
-
-export default function CippDatatable({ path, params, ...rest }) {
- const [graphFilter, setGraphFilter] = React.useState(params?.Parameters?.$filter)
- const {
- data = [],
- isFetching,
- error,
- refetch,
- } = useListDatatableQuery({ path, params: { $filter: graphFilter, ...params } })
-
- let anonimized = false // Assuming default value is false
- const regex = new RegExp('^[A-Z0-9]+$')
- const principalNameOrUPN =
- data[0]?.userPrincipalName ??
- data[0]?.UPN ??
- data.Results?.[0]?.upn ??
- data.Results?.[0]?.userPrincipalName
-
- if (principalNameOrUPN && regex.test(principalNameOrUPN)) {
- anonimized = true
- }
-
- var defaultFilterText = ''
- if (params?.Parameters?.$filter) {
- defaultFilterText = 'Graph: ' + params?.Parameters?.$filter
- }
- return (
- <>
- {anonimized && (
-
- This table might contain anonymized data. Please check this
-
- documentation link
-
- to resolve this.
-
- )}
- {data?.Metadata?.Queued && {data?.Metadata?.QueueMessage} }
- refetch()}
- graphFilterFunction={setGraphFilter}
- />
- >
- )
-}
-
-CippDatatable.propTypes = {
- path: PropTypes.string.isRequired,
- params: PropTypes.object,
- ...CippTablePropTypes,
-}
diff --git a/src/data/alerts.json b/src/data/alerts.json
index 835216740c4d..0648464c74ff 100644
--- a/src/data/alerts.json
+++ b/src/data/alerts.json
@@ -19,6 +19,11 @@
"label": "Alert on changed admin Passwords",
"recommendedRunInterval": "30m"
},
+ {
+ "name": "InactiveLicensedUsers",
+ "label": "Alert on licensed users that have not logged in for 90 days",
+ "recommendedRunInterval": "1d"
+ },
{
"name": "QuotaUsed",
"label": "Alert on % mailbox quota used",
@@ -99,5 +104,16 @@
"name": "DeviceCompliance",
"label": "Alert on device compliance issues",
"recommendedRunInterval": "4h"
+ },
+ {
+ "name": "BreachAlert",
+ "label": "Alert on (new) potentially breached passwords. Generates an alert if a password is found to be breached.",
+ "recommendedRunInterval": "7d"
+ },
+ {
+ "name": "HuntressRogueApps",
+ "label": "Alert on Huntress Rogue Apps detected",
+ "recommendedRunInterval": "4h",
+ "description": "Huntress has provided a repository of known rogue apps that are commonly used in BEC, data exfiltration and other Microsoft 365 attacks. This alert will notify you if any of these apps are detected in the selected tenant(s). For more information, see https://huntresslabs.github.io/rogueapps/ ."
}
]
diff --git a/src/data/standards.json b/src/data/standards.json
index ef14f236cd1a..3bce57411d37 100644
--- a/src/data/standards.json
+++ b/src/data/standards.json
@@ -7,24 +7,28 @@
"docsDescription": "",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.MailContacts.GeneralContact",
- "label": "General Contact"
+ "label": "General Contact",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.MailContacts.SecurityContact",
- "label": "Security Contact"
+ "label": "Security Contact",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.MailContacts.MarketingContact",
- "label": "Marketing Contact"
+ "label": "Marketing Contact",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.MailContacts.TechContact",
- "label": "Technical Contact"
+ "label": "Technical Contact",
+ "required": false
}
],
"label": "Set contact e-mails",
@@ -69,42 +73,45 @@
"helpText": "Sets the branding for the tenant. This includes the login page, and the Office 365 portal.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.Branding.signInPageText",
- "label": "Sign-in page text"
+ "label": "Sign-in page text",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.Branding.usernameHintText",
- "label": "Username hint Text"
+ "label": "Username hint Text",
+ "required": false
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.Branding.hideAccountResetCredentials",
"label": "Hide self-service password reset"
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Visual Template",
"name": "standards.Branding.layoutTemplateType",
- "values": [
+ "options": [
{
"label": "Full-screen background",
"value": "default"
},
{
- "label": "Parial-screen background",
+ "label": "Partial-screen background",
"value": "verticalSplit"
}
]
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.Branding.isHeaderShown",
"label": "Show header"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.Branding.isFooterShown",
"label": "Show footer"
}
@@ -186,10 +193,11 @@
"helpText": "Enables and sets Idle session timeout for Microsoft 365 to 1 hour. This policy affects most M365 web apps",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.ActivityBasedTimeout.timeout",
- "values": [
+ "options": [
{
"label": "1 Hour",
"value": "01:00:00"
@@ -227,7 +235,7 @@
"docsDescription": "Uses the CIPP functionality that deploys applications across an entire tenant base as a standard.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.AppDeploy.appids",
"label": "Application IDs, comma separated"
}
@@ -285,10 +293,11 @@
"docsDescription": "Sets the Authenticator Lite state to enabled. This allows users to use the Authenticator Lite built into the Outlook app instead of the full Authenticator app.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.PWcompanionAppAllowedState.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "enabled"
@@ -349,14 +358,15 @@
"name": "standards.TAP",
"cat": "Entra (AAD) Standards",
"tag": ["lowimpact"],
- "helpText": "Enables TAP and sets the default TAP lifetime to 1 hour. This configuration also allows you to select is a TAP is single use or multi-logon.",
+ "helpText": "Enables TAP and sets the default TAP lifetime to 1 hour. This configuration also allows you to select if a TAP is single use or multi-logon.",
"docsDescription": "Enables Temporary Password generation for the tenant.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select TAP Lifetime",
"name": "standards.TAP.config",
- "values": [
+ "options": [
{
"label": "Only Once",
"value": "true"
@@ -394,10 +404,11 @@
"helpText": "Sets the state of the Cross-tenant access setting to trust external MFA. This allows guest users to use their home tenant MFA to access your tenant.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.ExternalMFATrusted.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "true"
@@ -455,10 +466,11 @@
"docsDescription": "Sets the state of the registration campaign for the tenant. If enabled nudges users to set up the Microsoft Authenticator during sign-in.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.NudgeMFA.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "enabled"
@@ -539,9 +551,10 @@
"helpText": "This standard disables all self service licenses and enables all exclusions",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.DisableSelfServiceLicenses.Exclusions",
- "label": "License Ids to exclude from this standard"
+ "label": "License Ids to exclude from this standard",
+ "required": false
}
],
"label": "Disable Self Service Licensing",
@@ -570,9 +583,10 @@
"docsDescription": "Requires users to get administrator consent before sharing data with applications. You can preapprove specific applications.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.OauthConsent.AllowedApps",
- "label": "Allowed application IDs, comma separated"
+ "label": "Allowed application IDs, comma separated",
+ "required": false
}
],
"label": "Require admin consent for applications (Prevent OAuth phishing)",
@@ -593,6 +607,43 @@
"powershellEquivalent": "Update-MgPolicyAuthorizationPolicy",
"recommendedBy": []
},
+ {
+ "name": "standards.GuestInvite",
+ "cat": "Entra (AAD) Standards",
+ "tag": ["mediumimpact"],
+ "helpText": "This setting controls who can invite guests to your directory to collaborate on resources secured by your company, such as SharePoint sites or Azure resources.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "multiple": false,
+ "label": "Who can send invites?",
+ "name": "standards.GuestInvite.allowInvitesFrom",
+ "options": [
+ {
+ "label": "Everyone",
+ "value": "everyone"
+ },
+ {
+ "label": "Admins, Guest inviters and All Members",
+ "value": "adminsGuestInvitersAndAllMembers"
+ },
+ {
+ "label": "Admins and Guest inviters",
+ "value": "adminsAndGuestInviters"
+ },
+ {
+ "label": "None",
+ "value": "none"
+ }
+ ]
+ }
+ ],
+ "label": "Guest Invite setting",
+ "impact": "Medium Impact",
+ "impactColour": "warning",
+ "powershellEquivalent": "",
+ "recommendedBy": []
+ },
{
"name": "standards.UndoOauth",
"cat": "Entra (AAD) Standards",
@@ -648,7 +699,7 @@
"name": "standards.DisableEmail",
"cat": "Entra (AAD) Standards",
"tag": ["highimpact"],
- "helpText": "This blocks users from using email as an MFA method. This disables the email OTP option for guest users, and instead promts them to create a Microsoft account.",
+ "helpText": "This blocks users from using email as an MFA method. This disables the email OTP option for guest users, and instead prompts them to create a Microsoft account.",
"addedComponent": [],
"label": "Disables Email as an MFA method",
"impact": "High Impact",
@@ -689,7 +740,7 @@
"docsDescription": "Sets the e-mail address to which outbound spam alerts are sent.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.OutBoundSpamAlert.OutboundSpamContact",
"label": "Outbound spam contact"
}
@@ -721,10 +772,11 @@
"docsDescription": "Sets the global quarantine notification interval for the tenant. This is the time between the quarantine notification emails are sent out to users. Default is 24 hours.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.GlobalQuarantineNotifications.NotificationInterval",
- "values": [
+ "options": [
{
"label": "4 hours",
"value": "04:00:00"
@@ -767,10 +819,11 @@
"docsDescription": "Sets the default Focused Inbox state for the tenant. This can be overridden by the user in their Outlook settings. For more information, see [Microsoft's documentation.](https://support.microsoft.com/en-us/office/focused-inbox-for-outlook-f445ad7f-02f4-4294-a82e-71d8964e3978)",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.FocusedInbox.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "enabled"
@@ -796,10 +849,11 @@
"docsDescription": "Sets the default state for Cloud Message Recall for the tenant. By default this is enabled. You can read more about the feature [here.](https://techcommunity.microsoft.com/t5/exchange-team-blog/cloud-based-message-recall-in-exchange-online/ba-p/3744714)",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.CloudMessageRecall.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "true"
@@ -862,10 +916,11 @@
"docsDescription": "Adds or removes indicators to e-mail messages received from external senders in Outlook. You can read more about this feature on [Microsoft's Exchange Team Blog.](https://techcommunity.microsoft.com/t5/exchange-team-blog/native-external-sender-callouts-on-email-in-outlook/ba-p/2250098)",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.SpoofWarn.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "enabled"
@@ -880,7 +935,7 @@
"label": "Enable or disable 'external' warning in Outlook",
"impact": "Low Impact",
"impactColour": "info",
- "powershellEquivalent": "et-ExternalInOutlook –Enabled $true or $false",
+ "powershellEquivalent": "et-ExternalInOutlook \u2013Enabled $true or $false",
"recommendedBy": ["CIS"]
},
{
@@ -910,10 +965,11 @@
"helpText": "Sets the default state for automatically turning meetings into Teams meetings for the tenant. This can be overridden by the user in Outlook.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.TeamsMeetingsByDefault.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "true"
@@ -1019,10 +1075,11 @@
},
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select Sharing Level",
"name": "standards.calDefault.permissionlevel",
- "values": [
+ "options": [
{
"label": "Owner - The user can create, read, edit, and delete all items in the folder, and create subfolders. The user is both folder owner and folder contact.",
"value": "Owner"
@@ -1109,10 +1166,11 @@
"helpText": "Sets the shorten meetings settings on a tenant level. This will shorten meetings by the selected amount of minutes. Valid values are 0 to 29. Short meetings are under 60 minutes, long meetings are over 60 minutes.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.ShortenMeetings.ShortenEventScopeDefault",
- "values": [
+ "options": [
{
"label": "Disabled/None",
"value": "None"
@@ -1154,10 +1212,11 @@
"docsDescription": "",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.Bookings.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "true"
@@ -1239,10 +1298,11 @@
"docsDescription": "Set the state of the built-in Report button in Outlook. This gives the users the ability to report emails as spam or phish.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select value",
"name": "standards.UserSubmissions.state",
- "values": [
+ "options": [
{
"label": "Enabled",
"value": "enable"
@@ -1254,8 +1314,9 @@
]
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.UserSubmissions.email",
+ "required": false,
"label": "Destination email address"
}
],
@@ -1299,7 +1360,7 @@
"docsDescription": "Sets a e-mail address to alert when a User requests to release a quarantined message. This is useful for monitoring and ensuring that the correct messages are released.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.QuarantineRequestAlert.NotifyUser",
"label": "E-mail to receive the alert"
}
@@ -1317,17 +1378,17 @@
"helpText": "This creates a safelink policy that automatically scans, tracks, and and enables safe links for Email, Office, and Teams for both external and internal senders",
"addedComponent": [
{
- "type": "boolean",
+ "type": "switch",
"label": "AllowClickThrough",
"name": "standards.SafeLinksPolicy.AllowClickThrough"
},
{
- "type": "boolean",
+ "type": "switch",
"label": "DisableUrlRewrite",
"name": "standards.SafeLinksPolicy.DisableUrlRewrite"
},
{
- "type": "boolean",
+ "type": "switch",
"label": "EnableOrganizationBranding",
"name": "standards.SafeLinksPolicy.EnableOrganizationBranding"
}
@@ -1361,34 +1422,35 @@
"default": 1
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Show first contact safety tip",
"name": "standards.AntiPhishPolicy.EnableFirstContactSafetyTips",
"default": true
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Show user impersonation safety tip",
"name": "standards.AntiPhishPolicy.EnableSimilarUsersSafetyTips",
"default": true
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Show domain impersonation safety tip",
"name": "standards.AntiPhishPolicy.EnableSimilarDomainsSafetyTips",
"default": true
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Show user impersonation unusual characters safety tip",
"name": "standards.AntiPhishPolicy.EnableUnusualCharactersSafetyTips",
"default": true
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "If the message is detected as spoof by spoof intelligence",
"name": "standards.AntiPhishPolicy.AuthenticationFailAction",
- "values": [
+ "options": [
{
"label": "Quarantine the message",
"value": "Quarantine"
@@ -1400,10 +1462,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Quarantine policy for Spoof",
"name": "standards.AntiPhishPolicy.SpoofQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1419,10 +1482,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "If a message is detected as user impersonation",
"name": "standards.AntiPhishPolicy.TargetedUserProtectionAction",
- "values": [
+ "options": [
{
"label": "Move to Junk Folder",
"value": "MoveToJmf"
@@ -1438,10 +1502,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Quarantine policy for user impersonation",
"name": "standards.AntiPhishPolicy.TargetedUserQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1457,10 +1522,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "If a message is detected as domain impersonation",
"name": "standards.AntiPhishPolicy.TargetedDomainProtectionAction",
- "values": [
+ "options": [
{
"label": "Move to Junk Folder",
"value": "MoveToJmf"
@@ -1476,10 +1542,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Quarantine policy for domain impersonation",
"name": "standards.AntiPhishPolicy.TargetedDomainQuarantineTag",
- "values": [
+ "options": [
{
"label": "DefaultFullAccessWithNotificationPolicy",
"value": "DefaultFullAccessWithNotificationPolicy"
@@ -1495,10 +1562,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "If Mailbox Intelligence detects an impersonated user",
"name": "standards.AntiPhishPolicy.MailboxIntelligenceProtectionAction",
- "values": [
+ "options": [
{
"label": "Move to Junk Folder",
"value": "MoveToJmf"
@@ -1514,10 +1582,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Apply quarantine policy",
"name": "standards.AntiPhishPolicy.MailboxIntelligenceQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1552,10 +1621,11 @@
"helpText": "This creates a Safe Attachment policy",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Action",
"name": "standards.SafeAttachmentPolicy.Action",
- "values": [
+ "options": [
{
"label": "Allow",
"value": "Allow"
@@ -1571,10 +1641,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "QuarantineTag",
"name": "standards.SafeAttachmentPolicy.QuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1590,14 +1661,15 @@
]
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Redirect",
"name": "standards.SafeAttachmentPolicy.Redirect"
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.SafeAttachmentPolicy.RedirectAddress",
- "label": "Redirect Address"
+ "label": "Redirect Address",
+ "required": false
}
],
"label": "Default Safe Attachment Policy",
@@ -1613,10 +1685,11 @@
"helpText": "This creates a Atp policy that enables Defender for Office 365 for Sharepoint, OneDrive and Microsoft Teams.",
"addedComponent": [
{
- "type": "boolean",
+ "type": "switch",
"label": "Allow people to click through Protected View even if Safe Documents identified the file as malicious",
"name": "standards.AtpPolicyForO365.AllowSafeDocsOpen",
- "default": false
+ "default": false,
+ "required": false
}
],
"label": "Default Atp Policy For O365",
@@ -1632,10 +1705,11 @@
"helpText": "This creates a Malware filter policy that enables the default File filter and Zero-hour auto purge for malware.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "FileTypeAction",
"name": "standards.MalwareFilterPolicy.FileTypeAction",
- "values": [
+ "options": [
{
"label": "Reject",
"value": "Reject"
@@ -1647,15 +1721,17 @@
]
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.MalwareFilterPolicy.OptionalFileTypes",
+ "required": false,
"label": "Optional File Types, Comma separated"
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "QuarantineTag",
"name": "standards.MalwareFilterPolicy.QuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1671,23 +1747,27 @@
]
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Enable Internal Sender Admin Notifications",
+ "required": false,
"name": "standards.MalwareFilterPolicy.EnableInternalSenderAdminNotifications"
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.MalwareFilterPolicy.InternalSenderAdminAddress",
+ "required": false,
"label": "Internal Sender Admin Address"
},
{
- "type": "boolean",
+ "type": "switch",
"label": "Enable External Sender Admin Notifications",
+ "required": false,
"name": "standards.MalwareFilterPolicy.EnableExternalSenderAdminNotifications"
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.MalwareFilterPolicy.ExternalSenderAdminAddress",
+ "required": false,
"label": "External Sender Admin Address"
}
],
@@ -1710,10 +1790,11 @@
"default": 7
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Spam Action",
"name": "standards.SpamFilterPolicy.SpamAction",
- "values": [
+ "options": [
{
"label": "Quarantine the message",
"value": "Quarantine"
@@ -1725,10 +1806,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Spam Quarantine Tag",
"name": "standards.SpamFilterPolicy.SpamQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1744,10 +1826,10 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
"label": "High Confidence Spam Action",
"name": "standards.SpamFilterPolicy.HighConfidenceSpamAction",
- "values": [
+ "options": [
{
"label": "Quarantine the message",
"value": "Quarantine"
@@ -1759,10 +1841,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "High Confidence Spam Quarantine Tag",
"name": "standards.SpamFilterPolicy.HighConfidenceSpamQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1778,10 +1861,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Bulk Spam Action",
"name": "standards.SpamFilterPolicy.BulkSpamAction",
- "values": [
+ "options": [
{
"label": "Quarantine the message",
"value": "Quarantine"
@@ -1793,10 +1877,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Bulk Quarantine Tag",
"name": "standards.SpamFilterPolicy.BulkQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1812,10 +1897,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Phish Spam Action",
"name": "standards.SpamFilterPolicy.PhishSpamAction",
- "values": [
+ "options": [
{
"label": "Quarantine the message",
"value": "Quarantine"
@@ -1827,10 +1913,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Phish Quarantine Tag",
"name": "standards.SpamFilterPolicy.PhishQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1846,10 +1933,11 @@
]
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "High Confidence Phish Quarantine Tag",
"name": "standards.SpamFilterPolicy.HighConfidencePhishQuarantineTag",
- "values": [
+ "options": [
{
"label": "AdminOnlyAccessPolicy",
"value": "AdminOnlyAccessPolicy"
@@ -1896,54 +1984,63 @@
"helpText": "Sets the branding profile for the Intune Company Portal app. This is a tenant wide setting and overrules any settings set on the app level.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.displayName",
- "label": "Organization name"
+ "label": "Organization name",
+ "required": false
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.intuneBrandingProfile.showLogo",
"label": "Show logo"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.intuneBrandingProfile.showDisplayNameNextToLogo",
- "label": "Show organization name next to logo"
+ "label": "Show organization name next to logo",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.contactITName",
- "label": "Contact IT name"
+ "label": "Contact IT name",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.contactITPhoneNumber",
- "label": "Contact IT phone number"
+ "label": "Contact IT phone number",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.contactITEmailAddress",
- "label": "Contact IT email address"
+ "label": "Contact IT email address",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.contactITNotes",
- "label": "Contact IT notes"
+ "label": "Contact IT notes",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.onlineSupportSiteName",
- "label": "Online support site name"
+ "label": "Online support site name",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.onlineSupportSiteUrl",
- "label": "Online support site URL"
+ "label": "Online support site URL",
+ "required": false
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.intuneBrandingProfile.privacyUrl",
- "label": "Privacy statement URL"
+ "label": "Privacy statement URL",
+ "required": false
}
],
"label": "Set Intune Company Portal branding profile",
@@ -1952,6 +2049,40 @@
"powershellEquivalent": "Graph API",
"recommendedBy": []
},
+ {
+ "name": "standards.IntuneComplianceSettings",
+ "cat": "Intune Standards",
+ "tag": ["lowimpact"],
+ "helpText": "Sets the mark devices with no compliance policy assigned as compliance/non compliant and Compliance status validity period.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "multiple": false,
+ "name": "standards.IntuneComplianceSettings.secureByDefault",
+ "label": "Mark devices with no compliance policy as",
+ "options": [
+ {
+ "label": "Compliant",
+ "value": "false"
+ },
+ {
+ "label": "Non-Compliant",
+ "value": "true"
+ }
+ ]
+ },
+ {
+ "type": "number",
+ "name": "standards.IntuneComplianceSettings.deviceComplianceCheckinThresholdDays",
+ "label": "Compliance status validity period (days)"
+ }
+ ],
+ "label": "Set Intune Compliance Settings",
+ "impact": "Low Impact",
+ "impactColour": "info",
+ "powershellEquivalent": "",
+ "recommendedBy": []
+ },
{
"name": "standards.intuneDeviceReg",
"cat": "Intune Standards",
@@ -1985,14 +2116,23 @@
"name": "standards.DeletedUserRentention",
"cat": "SharePoint Standards",
"tag": ["lowimpact"],
- "helpText": "Sets the retention period for deleted users OneDrive to the specified number of years. The default is 1 year.",
- "docsDescription": "When a OneDrive user gets deleted, the personal SharePoint site is saved for selected time in years and data can be retrieved from it.",
+ "helpText": "Sets the retention period for deleted users OneDrive to the specified period of time. The default is 30 days.",
+ "docsDescription": "When a OneDrive user gets deleted, the personal SharePoint site is saved for selected amount of time that data can be retrieved from it.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"name": "standards.DeletedUserRentention.Days",
- "label": "Retention in years (Default 1)",
- "values": [
+ "label": "Retention time (Default 30 days)",
+ "options": [
+ {
+ "label": "30 days",
+ "value": "30"
+ },
+ {
+ "label": "90 days",
+ "value": "90"
+ },
{
"label": "1 year",
"value": "365"
@@ -2151,10 +2291,11 @@
"helpText": "If disabled, the button Add shortcut to OneDrive will be removed and users in the tenant will no longer be able to add new shortcuts to their OneDrive. Existing shortcuts will remain functional",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Add Shortcuts To OneDrive button state",
"name": "standards.DisableAddShortcutsToOneDrive.state",
- "values": [
+ "options": [
{
"label": "Disabled",
"value": "true"
@@ -2179,10 +2320,11 @@
"helpText": "If disabled, users in the tenant will no longer be able to use the Sync button to sync SharePoint content on all sites. However, existing synced content will remain functional on the user's computer.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "SharePoint Sync Button state",
"name": "standards.SPSyncButtonState.state",
- "values": [
+ "options": [
{
"label": "Disabled",
"value": "true"
@@ -2220,10 +2362,11 @@
"helpText": "Sets the default sharing level for OneDrive and Sharepoint. This is a tenant wide setting and overrules any settings set on the site level",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"label": "Select Sharing Level",
"name": "standards.sharingCapability.Level",
- "values": [
+ "options": [
{
"label": "Users can share only with people in the organization. No external sharing is allowed.",
"value": "disabled"
@@ -2282,7 +2425,7 @@
"helpText": "Sets the file extensions that are excluded from syncing with OneDrive. These files will be blocked from upload. '*.' is automatically added to the extension and can be omitted.",
"addedComponent": [
{
- "type": "input",
+ "type": "textField",
"name": "standards.ExcludedfileExt.ext",
"label": "Extensions, Comma separated"
}
@@ -2324,16 +2467,17 @@
"helpText": "Restricts sharing to only users with the specified domain. This is useful for organizations that only want to share with their own domain.",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"name": "standards.sharingDomainRestriction.Mode",
"label": "Limit external sharing by domains",
- "values": [
+ "options": [
{
"label": "Off",
"value": "none"
},
{
- "label": "Restirct sharing to specific domains",
+ "label": "Restrict sharing to specific domains",
"value": "allowList"
},
{
@@ -2343,9 +2487,10 @@
]
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.sharingDomainRestriction.Domains",
- "label": "Domains to allow/block, comma separated"
+ "label": "Domains to allow/block, comma separated",
+ "required": false
}
],
"label": "Restrict sharing to a specific domain",
@@ -2361,10 +2506,11 @@
"helpText": "Defines the CIS recommended global meeting policy for Teams. This includes AllowAnonymousUsersToJoinMeeting, AllowAnonymousUsersToStartMeeting, AutoAdmittedUsers, AllowPSTNUsersToBypassLobby, MeetingChatEnabledType, DesignatedPresenterRoleMode, AllowExternalParticipantGiveRequestControl",
"addedComponent": [
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"name": "standards.TeamsGlobalMeetingPolicy.DesignatedPresenterRoleMode",
"label": "Default value of the `Who can present?`",
- "values": [
+ "options": [
{
"label": "EveryoneUserOverride",
"value": "EveryoneUserOverride"
@@ -2382,6 +2528,31 @@
"value": "OrganizerOnlyUserOverride"
}
]
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsGlobalMeetingPolicy.AllowAnonymousUsersToJoinMeeting",
+ "label": "Allow anonymous users to join meeting"
+ },
+ {
+ "type": "autoComplete",
+ "multiple": false,
+ "name": "standards.TeamsGlobalMeetingPolicy.MeetingChatEnabledType",
+ "label": "Meeting chat policy",
+ "options": [
+ {
+ "label": "On for everyone",
+ "value": "Enabled"
+ },
+ {
+ "label": "On for everyone but anonymous users",
+ "value": "EnabledExceptAnonymous"
+ },
+ {
+ "label": "Off for everyone",
+ "value": "Disabled"
+ }
+ ]
}
],
"label": "Define Global Meeting Policy for Teams",
@@ -2398,7 +2569,7 @@
"docsDescription": "Teams channel email addresses are an optional feature that allows users to email the Teams channel directly.",
"addedComponent": [
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsEmailIntegration.AllowEmailIntoChannel",
"label": "Allow channel emails"
}
@@ -2416,27 +2587,27 @@
"helpText": "Ensure external file sharing in Teams is enabled for only approved cloud storage services.",
"addedComponent": [
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalFileSharing.AllowGoogleDrive",
"label": "Allow Google Drive"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalFileSharing.AllowShareFile",
"label": "Allow ShareFile"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalFileSharing.AllowBox",
"label": "Allow Box"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalFileSharing.AllowDropBox",
"label": "Allow Dropbox"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalFileSharing.AllowEgnyte",
"label": "Allow Egnyte"
}
@@ -2447,6 +2618,35 @@
"powershellEquivalent": "Set-CsTeamsClientConfiguration -AllowGoogleDrive $false -AllowShareFile $false -AllowBox $false -AllowDropBox $false -AllowEgnyte $false",
"recommendedBy": ["CIS 3.0"]
},
+ {
+ "name": "standards.TeamsEnrollUser",
+ "cat": "Teams Standards",
+ "tag": ["lowimpact"],
+ "helpText": "Controls whether users with this policy can set the voice profile capture and enrollment through the Recognition tab in their Teams client settings.",
+ "docsDescription": "Controls whether users with this policy can set the voice profile capture and enrollment through the Recognition tab in their Teams client settings.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "name": "standards.TeamsEnrollUser.EnrollUserOverride",
+ "label": "Voice and Face Enrollment",
+ "options": [
+ {
+ "label": "Disabled",
+ "value": "Disabled"
+ },
+ {
+ "label": "Enabled",
+ "value": "Enabled"
+ }
+ ]
+ }
+ ],
+ "label": "Default voice and face enrollment",
+ "impact": "Low Impact",
+ "impactColour": "info",
+ "powershellEquivalent": "Set-CsTeamsMeetingPolicy -Identity Global -EnrollUserOverride $false",
+ "recommendedBy": []
+ },
{
"name": "standards.TeamsExternalAccessPolicy",
"cat": "Teams Standards",
@@ -2455,17 +2655,17 @@
"docsDescription": "Sets the properties of the Global external access policy. External access policies determine whether or not your users can: 1) communicate with users who have Session Initiation Protocol (SIP) accounts with a federated organization; 2) communicate with users who are using custom applications built with Azure Communication Services; 3) access Skype for Business Server over the Internet, without having to log on to your internal network; 4) communicate with users who have SIP accounts with a public instant messaging (IM) provider such as Skype; and, 5) communicate with people who are using Teams with an account that's not managed by an organization.",
"addedComponent": [
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalAccessPolicy.EnableFederationAccess",
"label": "Allow communication from trusted organizations"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalAccessPolicy.EnablePublicCloudAccess",
"label": "Allow user to communicate with Skype users"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsExternalAccessPolicy.EnableTeamsConsumerAccess",
"label": "Allow communication with unmanaged Teams accounts"
}
@@ -2484,20 +2684,21 @@
"docsDescription": "Sets the properties of the Global federation configuration. Federation configuration settings determine whether or not your users can communicate with users who have SIP accounts with a federated organization.",
"addedComponent": [
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsFederationConfiguration.AllowTeamsConsumer",
"label": "Allow users to communicate with other organizations"
},
{
- "type": "boolean",
+ "type": "switch",
"name": "standards.TeamsFederationConfiguration.AllowPublicUsers",
"label": "Allow users to communicate with Skype Users"
},
{
- "type": "Select",
+ "type": "autoComplete",
+ "multiple": false,
"name": "standards.TeamsFederationConfiguration.DomainControl",
"label": "Communication Mode",
- "values": [
+ "options": [
{
"label": "Allow all external domains",
"value": "AllowAllExternal"
@@ -2517,9 +2718,10 @@
]
},
{
- "type": "input",
+ "type": "textField",
"name": "standards.TeamsFederationConfiguration.DomainList",
- "label": "Domains, Comma separated"
+ "label": "Domains, Comma separated",
+ "required": false
}
],
"label": "Federation Configuration for Microsoft Teams",
@@ -2527,5 +2729,414 @@
"impactColour": "warning",
"powershellEquivalent": "Set-CsTenantFederationConfiguration",
"recommendedBy": []
+ },
+ {
+ "name": "standards.TeamsMessagingPolicy",
+ "cat": "Teams Standards",
+ "tag": ["mediumimpact"],
+ "helpText": "Sets the properties of the Global messaging policy.",
+ "docsDescription": "Sets the properties of the Global messaging policy. Messaging policies control which chat and channel messaging features are available to users in Teams.",
+ "addedComponent": [
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.AllowOwnerDeleteMessage",
+ "label": "Allow Owner to Delete Messages",
+ "default": false
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.AllowUserDeleteMessage",
+ "label": "Allow User to Delete Messages",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.AllowUserEditMessage",
+ "label": "Allow User to Edit Messages",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.AllowUserDeleteChat",
+ "label": "Allow User to Delete Chats",
+ "default": true
+ },
+ {
+ "type": "autoComplete",
+ "multiple": false,
+ "name": "standards.TeamsMessagingPolicy.ReadReceiptsEnabledType",
+ "label": "Read Receipts Enabled Type",
+ "options": [
+ {
+ "label": "User controlled",
+ "value": "UserPreference"
+ },
+ {
+ "label": "Turned on for everyone",
+ "value": "Everyone"
+ },
+ {
+ "label": "Turned off for everyone",
+ "value": "None"
+ }
+ ]
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.CreateCustomEmojis",
+ "label": "Allow Creating Custom Emojis",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.DeleteCustomEmojis",
+ "label": "Allow Deleting Custom Emojis",
+ "default": false
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.AllowSecurityEndUserReporting",
+ "label": "Allow reporting message as security concern",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.TeamsMessagingPolicy.AllowCommunicationComplianceEndUserReporting",
+ "label": "Allow reporting message as inappropriate content",
+ "default": true
+ }
+ ],
+ "label": "Global Messaging Policy for Microsoft Teams",
+ "impact": "Medium Impact",
+ "impactColour": "warning",
+ "powershellEquivalent": "Set-CsTeamsMessagingPolicy",
+ "recommendedBy": []
+ },
+ {
+ "name": "standards.AutopilotStatusPage",
+ "cat": "Device Management Standards",
+ "tag": ["lowimpact"],
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "helpText": "Deploy the Autopilot Status Page, which shows progress during device setup through Autopilot.",
+ "docsDescription": "This standard allows configuration of the Autopilot Status Page, providing users with a visual representation of the progress during device setup. It includes options like timeout, logging, and retry settings.",
+ "addedComponent": [
+ {
+ "type": "number",
+ "name": "standards.AutopilotStatusPage.TimeOutInMinutes",
+ "label": "Timeout in minutes",
+ "default": 60
+ },
+ {
+ "type": "textField",
+ "name": "standards.AutopilotStatusPage.ErrorMessage",
+ "label": "Custom Error Message"
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.ShowProgress",
+ "label": "Show progress to users",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.EnableLog",
+ "label": "Turn on log collection",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.OBEEOnly",
+ "label": "Show status page only with OOBE setup",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.BlockDevice",
+ "label": "Block device usage during setup",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.AllowRetry",
+ "label": "Allow retry",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.AllowReset",
+ "label": "Allow reset",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotStatusPage.AllowFail",
+ "label": "Allow users to use device if setup fails",
+ "default": true
+ }
+ ],
+ "label": "Enable Autopilot Status Page",
+ "impact": "Low Impact",
+ "impactColour": "info",
+ "recommendedBy": []
+ },
+ {
+ "name": "standards.AutopilotProfile",
+ "cat": "Device Management Standards",
+ "tag": ["lowimpact"],
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "helpText": "Assign the appropriate Autopilot profile to streamline device deployment.",
+ "docsDescription": "This standard allows the deployment of Autopilot profiles to devices, including settings such as unique name templates, language options, and local admin privileges.",
+ "addedComponent": [
+ {
+ "type": "textField",
+ "name": "standards.AutopilotProfile.DisplayName",
+ "label": "Profile Display Name"
+ },
+ {
+ "type": "textField",
+ "name": "standards.AutopilotProfile.Description",
+ "label": "Profile Description"
+ },
+ {
+ "type": "textField",
+ "name": "standards.AutopilotProfile.DeviceNameTemplate",
+ "label": "Unique Device Name Template"
+ },
+ {
+ "type": "autoComplete",
+ "multiple": false,
+ "name": "standards.AutopilotProfile.Languages",
+ "label": "Languages",
+ "api": {
+ "url": "/languageList.json",
+ "labelField": "language",
+ "valueField": "tag"
+ }
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.CollectHash",
+ "label": "Convert all targeted devices to Autopilot",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.AssignToAllDevices",
+ "label": "Assign to all devices",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.SelfDeployingMode",
+ "label": "Enable Self-deploying Mode",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.HideTerms",
+ "label": "Hide Terms and Conditions",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.HidePrivacy",
+ "label": "Hide Privacy Settings",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.HideChangeAccount",
+ "label": "Hide Change Account Options",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.NotLocalAdmin",
+ "label": "Setup user as a standard user (not local admin)",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.AllowWhiteGlove",
+ "label": "Allow White Glove OOBE",
+ "default": true
+ },
+ {
+ "type": "switch",
+ "name": "standards.AutopilotProfile.AutoKeyboard",
+ "label": "Automatically configure keyboard",
+ "default": true
+ }
+ ],
+ "label": "Enable Autopilot Profile",
+ "impact": "Low Impact",
+ "impactColour": "info",
+ "recommendedBy": []
+ },
+ {
+ "name": "standards.IntuneTemplate",
+ "cat": "Templates",
+ "label": "Intune Template",
+ "multiple": true,
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "impact": "High",
+ "helpText": "Deploy and manage Intune templates across devices.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "multiple": false,
+ "name": "TemplateList",
+ "label": "Select Intune Template",
+ "api": {
+ "url": "/api/ListIntuneTemplates",
+ "labelField": "Displayname",
+ "valueField": "GUID",
+ "queryKey": "languages"
+ }
+ },
+ {
+ "name": "AssignTo",
+ "label": "Who should this template be assigned to?",
+ "type": "radio",
+ "options": [
+ { "label": "Do not assign", "value": "On" },
+ { "label": "Assign to all users", "value": "allLicensedUsers" },
+ { "label": "Assign to all devices", "value": "AllDevices" },
+ { "label": "Assign to all users and devices", "value": "AllDevicesAndUsers" },
+ { "label": "Assign to Custom Group", "value": "customGroup" }
+ ]
+ },
+ {
+ "type": "textField",
+ "required": false,
+ "name": "customGroup",
+ "label": "Enter the custom group name if you selected 'Assign to Custom Group'. Wildcards are allowed."
+ }
+ ]
+ },
+ {
+ "name": "standards.TransportRuleTemplate",
+ "label": "Transport Rule Template",
+ "cat": "Templates",
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "impact": "Medium",
+ "helpText": "Deploy transport rules to manage email flow.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "name": "transportRuleTemplate",
+ "label": "Select Transport Rule Template",
+ "api": {
+ "url": "/api/ListTransportRulesTemplates",
+ "labelField": "name",
+ "valueField": "GUID",
+ "queryKey": "ListTransportRulesTemplates"
+ }
+ }
+ ]
+ },
+ {
+ "name": "standards.ConditionalAccessTemplate",
+ "label": "Conditional Access Template",
+ "cat": "Templates",
+ "multiple": true,
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "impact": "High",
+ "helpText": "Manage conditional access policies for better security.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "name": "TemplateList",
+ "multiple": false,
+ "label": "Select Conditional Access Template",
+ "api": {
+ "url": "/api/ListCATemplates",
+ "labelField": "displayName",
+ "valueField": "GUID",
+ "queryKey": "ListCATemplates"
+ }
+ },
+ {
+ "name": "state",
+ "label": "What state should we deploy this template in?",
+ "type": "radio",
+ "options": [
+ { "value": "donotchange", "label": "Do not change state" },
+ { "value": "Enabled", "label": "Set to enabled" },
+ { "value": "Disabled", "label": "Set to disabled" },
+ { "value": "enabledForReportingButNotEnforced", "label": "Set to report only" }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "standards.ExchangeConnectorTemplate",
+ "label": "Exchange Connector Template",
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "impact": "Medium",
+ "helpText": "Deploy and manage Exchange connectors.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "name": "exConnectorTemplate",
+ "label": "Select Exchange Connector Template",
+ "api": {
+ "url": "/api/ListExConnectorTemplates",
+ "labelField": "name",
+ "valueField": "GUID",
+ "queryKey": "ListExConnectorTemplates"
+ }
+ }
+ ]
+ },
+ {
+ "name": "standards.GroupTemplate",
+ "label": "Group Template",
+ "multi": true,
+ "cat": "Templates",
+ "disabledFeatures": {
+ "report": true,
+ "warn": true,
+ "remediate": false
+ },
+ "impact": "Medium",
+ "helpText": "Deploy and manage group templates.",
+ "addedComponent": [
+ {
+ "type": "autoComplete",
+ "name": "groupTemplate",
+ "label": "Select Group Template",
+ "api": {
+ "url": "/api/ListGroupTemplates",
+ "labelField": "Displayname",
+ "valueField": "GUID",
+ "queryKey": "ListGroupTemplates"
+ }
+ }
+ ]
}
]
diff --git a/src/store/api/app.js b/src/store/api/app.js
deleted file mode 100644
index 3eaa06328f84..000000000000
--- a/src/store/api/app.js
+++ /dev/null
@@ -1,142 +0,0 @@
-import { baseApi } from 'src/store/api/baseApi'
-
-export const appApi = baseApi.injectEndpoints({
- endpoints: (builder) => ({
- loadVersions: builder.query({
- queryFn: (_args, _baseQueryApi, _options, baseQuery) =>
- baseQuery({ path: '/version_latest.txt' }).then(({ data }) =>
- baseQuery({
- path: '/api/GetVersion',
- params: { localversion: data.replace(/(\r\n|\n|\r)/gm, '') },
- }),
- ),
- }),
- loadVersionLocal: builder.query({
- query: () => ({ path: '/version_latest.txt' }),
- }),
- loadVersionRemote: builder.query({
- query: (localVersion) => ({
- path: '/api/GetVersion',
- params: { localversion: localVersion },
- }),
- }),
- loadAlertsDash: builder.query({
- queryFn: (_args, _baseQueryApi, _options, baseQuery) =>
- baseQuery({ path: '/version_latest.txt' }).then(({ data }) =>
- baseQuery({
- path: '/api/GetCippAlerts',
- params: { localversion: data.replace(/(\r\n|\n|\r)/gm, '') },
- }),
- ),
- }),
- loadDash: builder.query({
- query: (localVersion) => ({
- path: '/api/GetDashboard',
- }),
- }),
- execPermissionsAccessCheck: builder.query({
- query: () => ({
- path: '/api/ExecAccessChecks',
- params: {
- Permissions: true,
- },
- }),
- }),
- execNotificationConfig: builder.query({
- query: ({
- email,
- webhook,
- tokenUpdater,
- removeUser,
- removeStandard,
- addPolicy,
- addUser,
- addStandardsDeploy,
- addChocoApp,
- onePerTenant,
- sendtoIntegration,
- includeTenantId,
- logsToInclude,
- Severity,
- }) => ({
- path: '/api/ExecNotificationConfig',
- data: {
- email: email,
- webhook: webhook,
- tokenUpdater: tokenUpdater,
- removeUser: removeUser,
- removeStandard: removeStandard,
- addPolicy: addPolicy,
- addUser: addUser,
- addStandardsDeploy: addStandardsDeploy,
- addChocoApp: addChocoApp,
- onePerTenant: onePerTenant,
- logsToInclude: logsToInclude,
- Severity: Severity,
- sendtoIntegration: sendtoIntegration,
- includeTenantId: includeTenantId,
- },
- method: 'post',
- }),
- }),
- execTenantsAccessCheck: builder.query({
- query: ({ tenantDomains }) => ({
- path: '/api/ExecAccessChecks',
- params: {
- Tenants: true,
- },
- data: {
- tenantid: tenantDomains.join(','),
- },
- method: 'post',
- }),
- }),
- execClearCache: builder.query({
- query: ({ tenantsOnly }) => ({
- path: '/api/ListTenants',
- params: {
- ClearCache: true,
- TenantsOnly: tenantsOnly,
- },
- }),
- }),
- listNotificationConfig: builder.query({
- query: () => ({
- path: '/api/listNotificationConfig',
- }),
- }),
- genericPostRequest: builder.query({
- query: ({ path, values }) => ({
- path,
- data: values,
- method: 'post',
- }),
- }),
- genericGetRequest: builder.query({
- query: ({ path, params }) => ({
- path,
- params: params,
- method: 'GET',
- }),
- }),
- }),
-})
-
-export const {
- useLoadVersionLocalQuery,
- useLoadVersionRemoteQuery,
- useLoadVersionsQuery,
- useLoadDashQuery,
- useLoadAlertsDashQuery,
- useExecPermissionsAccessCheckQuery,
- useLazyExecPermissionsAccessCheckQuery,
- useExecTenantsAccessCheckQuery,
- useLazyExecTenantsAccessCheckQuery,
- useExecClearCacheQuery,
- useLazyExecClearCacheQuery,
- useLazyExecNotificationConfigQuery,
- useLazyListNotificationConfigQuery,
- useLazyGenericPostRequestQuery,
- useLazyGenericGetRequestQuery,
- useGenericGetRequestQuery,
-} = appApi
diff --git a/src/store/api/reports.js b/src/store/api/reports.js
deleted file mode 100644
index 83be1b4fa361..000000000000
--- a/src/store/api/reports.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { baseApi } from 'src/store/api/baseApi'
-
-export const reportsApi = baseApi.injectEndpoints({
- endpoints: (builder) => ({
- listBestPracticeAnalyser: builder.query({
- query: () => ({ path: '/api/BestPracticeAnalyser_List' }),
- }),
- execBestPracticeAnalyser: builder.mutation({
- query: () => ({ path: '/api/BestPracticeAnalyser_OrchestrationStarter' }),
- }),
- execDomainsAnalyser: builder.mutation({
- query: () => ({ path: '/api/DomainAnalyser_OrchestrationStarter' }),
- }),
- }),
-})
-
-export const {
- useListBestPracticeAnalyserQuery,
- useExecBestPracticeAnalyserMutation,
- useExecDomainsAnalyserMutation,
-} = reportsApi
diff --git a/src/store/api/users.js b/src/store/api/users.js
deleted file mode 100644
index 7ef16f12fdb3..000000000000
--- a/src/store/api/users.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { baseApi } from 'src/store/api/baseApi'
-
-export const usersApi = baseApi.injectEndpoints({
- endpoints: (builder) => ({
- editUser: builder.mutation({
- query: (user) => ({
- path: '/api/EditUser',
- method: 'post',
- data: user,
- }),
- }),
- listUsers: builder.query({
- query: ({ tenantDomain }) => ({
- path: '/api/ListUsers',
- params: {
- TenantFilter: tenantDomain,
- },
- }),
- }),
- listContacts: builder.query({
- query: ({ tenantDomain, ContactID }) => ({
- path: '/api/ListContacts',
- params: {
- TenantFilter: tenantDomain,
- ContactID,
- },
- }),
- }),
- listUser: builder.query({
- query: ({ tenantDomain, userId, IncludeLogonDetails }) => ({
- path: '/api/ListUsers',
- params: { userId, TenantFilter: tenantDomain, IncludeLogonDetails },
- }),
- transformResponse: (response) => {
- if (response?.length > 0) {
- return response[0]
- }
- return {}
- },
- }),
- listUserConditionalAccessPolicies: builder.query({
- query: ({ tenantDomain, userId }) => ({
- path: '/api/ListUserConditionalAccessPolicies',
- params: { userId, tenantFilter: tenantDomain },
- }),
- }),
- listUserSigninLogs: builder.query({
- query: ({ tenantDomain, userId }) => ({
- path: '/api/ListUserSigninLogs',
- params: { userId, tenantFilter: tenantDomain },
- }),
- }),
- addUser: builder.mutation({
- query: ({ user }) => ({
- path: '/api/AddUser',
- data: user,
- }),
- }),
- execBecCheck: builder.query({
- queryFn: async (_args, _baseQueryApi, _options, baseQuery) => {
- const startRequest = await baseQuery({
- path: '/api/execBECCheck',
- params: {
- userId: _args.userId,
- tenantFilter: _args.tenantFilter,
- userName: _args.userName,
- },
- })
- if (startRequest.error) {
- return { error: startRequest.error }
- }
-
- const GUID = startRequest.data?.GUID
-
- return new Promise((resolve) => {
- let retries = 0
- const interval = setInterval(async () => {
- const { data, error } = await baseQuery({
- path: '/api/execBECCheck',
- params: { GUID },
- })
- if (error) {
- clearInterval(interval)
- resolve({ error })
- }
- if (data.Results) {
- clearInterval(interval)
- resolve({
- error: {
- message: `Error: ${data.Results}`,
- status: 503,
- data: 'Request failed.',
- },
- })
- }
- if (!data['Waiting'] === true) {
- if (!Array.isArray(data['MSResults'])) {
- data['MSResults'] = []
- }
- clearInterval(interval)
- resolve({ data })
- }
- if (retries >= 60) {
- clearInterval(interval)
- resolve({
- error: {
- message: 'Failed to retrieve data in 5 minutes',
- status: 503,
- data: 'Request failed with status 503',
- },
- })
- }
- retries++
- }, 5000)
- })
- },
- }),
- }),
-})
-
-export const {
- useEditUserMutation,
- useListUsersQuery,
- useListUserQuery,
- useListContactsQuery,
- useListUserConditionalAccessPoliciesQuery,
- useListUserSigninLogsQuery,
- useAddUserMutation,
- useLazyExecBecCheckQuery,
-} = usersApi
-export default usersApi
diff --git a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx b/src/views/cipp/app-settings/SettingsExtensionMappings.jsx
deleted file mode 100644
index 6d7a63d2a3d0..000000000000
--- a/src/views/cipp/app-settings/SettingsExtensionMappings.jsx
+++ /dev/null
@@ -1,651 +0,0 @@
-import { useLazyGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app.js'
-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 CippAccordionItem from 'src/components/contentcards/CippAccordionItem'
-import { CippTable } from 'src/components/tables'
-import { CellTip } from 'src/components/tables/CellGenericFormat'
-import CippButtonCard from 'src/components/contentcards/CippButtonCard'
-
-/**
- * Retrieves and sets the extension mappings for HaloPSA and NinjaOne.
- *
- * @returns {JSX.Element} - JSX component representing the settings extension mappings.
- */
-export function SettingsExtensionMappings({ type }) {
- const [addedAttributes, setAddedAttribute] = React.useState(1)
- const [mappingArray, setMappingArray] = React.useState('defaultMapping')
- const [mappingValue, setMappingValue] = React.useState({})
- const [haloMappingsArray, setHaloMappingsArray] = React.useState([])
- const [ninjaMappingsArray, setNinjaMappingsArray] = React.useState([])
- const [HaloAutoMap, setHaloAutoMap] = React.useState(false)
- const [listHaloBackend, listBackendHaloResult = []] = useLazyGenericGetRequestQuery()
- const [listNinjaOrgsBackend, listBackendNinjaOrgsResult] = useLazyGenericGetRequestQuery()
- const [listNinjaFieldsBackend, listBackendNinjaFieldsResult] = useLazyGenericGetRequestQuery()
- const [setHaloExtensionconfig, extensionHaloConfigResult = []] = useLazyGenericPostRequestQuery()
- const [setNinjaOrgsExtensionconfig, extensionNinjaOrgsConfigResult] =
- useLazyGenericPostRequestQuery()
- const [setNinjaOrgsExtensionAutomap, extensionNinjaOrgsAutomapResult] =
- useLazyGenericPostRequestQuery()
- const [setNinjaFieldsExtensionconfig, extensionNinjaFieldsConfigResult] =
- useLazyGenericPostRequestQuery()
-
- const onHaloSubmit = () => {
- const originalFormat = haloMappingsArray.reduce((acc, item) => {
- acc[item.Tenant?.customerId] = { label: item.haloName, value: item.haloId }
- return acc
- }, {})
- setHaloExtensionconfig({
- path: 'api/ExecExtensionMapping?AddMapping=Halo',
- values: { mappings: originalFormat },
- }).then(() => {
- listHaloBackend({ path: 'api/ExecExtensionMapping?List=Halo' })
- setMappingValue({})
- })
- }
- const onNinjaOrgsSubmit = () => {
- const originalFormat = ninjaMappingsArray.reduce((acc, item) => {
- acc[item.Tenant?.customerId] = { label: item.ninjaName, value: item.ninjaId }
- return acc
- }, {})
-
- setNinjaOrgsExtensionconfig({
- path: 'api/ExecExtensionMapping?AddMapping=NinjaOrgs',
- values: { mappings: originalFormat },
- }).then(() => {
- listNinjaOrgsBackend({ path: 'api/ExecExtensionMapping?List=NinjaOrgs' })
- setMappingValue({})
- })
- }
-
- const onNinjaOrgsAutomap = async (values) => {
- await setNinjaOrgsExtensionAutomap({
- path: 'api/ExecExtensionMapping?AutoMapping=NinjaOrgs',
- values: { mappings: values },
- })
- await listNinjaOrgsBackend({
- path: 'api/ExecExtensionMapping?List=NinjaOrgs',
- })
- }
-
- const onNinjaFieldsSubmit = (values) => {
- setNinjaFieldsExtensionconfig({
- path: 'api/ExecExtensionMapping?AddMapping=NinjaFields',
- values: { mappings: values },
- })
- }
-
- const onHaloAutomap = () => {
- const newMappings = listBackendHaloResult.data?.Tenants.map(
- (tenant) => {
- const haloClient = listBackendHaloResult.data?.HaloClients.find(
- (client) => client.name === tenant.displayName,
- )
- if (haloClient) {
- console.log(haloClient)
- console.log(tenant)
- return {
- Tenant: tenant,
- haloName: haloClient.name,
- haloId: haloClient.value,
- }
- }
- },
- //filter out any undefined values
- ).filter((item) => item !== undefined)
- setHaloMappingsArray((currentHaloMappings) => [...currentHaloMappings, ...newMappings]).then(
- () => {
- listHaloBackend({ path: 'api/ExecExtensionMapping?List=Halo' })
- },
- )
- setHaloAutoMap(true)
- }
-
- useEffect(() => {
- if (listBackendHaloResult.isSuccess) {
- setHaloMappingsArray(
- Object.keys(listBackendHaloResult.data?.Mappings).map((key) => ({
- Tenant: listBackendHaloResult.data?.Tenants.find((tenant) => tenant.customerId === key),
- haloName: listBackendHaloResult.data?.Mappings[key].label,
- haloId: listBackendHaloResult.data?.Mappings[key].value,
- })),
- )
- }
- }, [listBackendHaloResult.isSuccess])
-
- useEffect(() => {
- if (listBackendNinjaOrgsResult.isSuccess) {
- setNinjaMappingsArray(
- Object.keys(listBackendNinjaOrgsResult.data?.Mappings).map((key) => ({
- Tenant: listBackendNinjaOrgsResult.data?.Tenants.find(
- (tenant) => tenant.customerId === key,
- ),
- ninjaName: listBackendNinjaOrgsResult.data?.Mappings[key].label,
- ninjaId: listBackendNinjaOrgsResult.data?.Mappings[key].value,
- })),
- )
- }
- }, [
- listBackendNinjaOrgsResult.data?.Mappings,
- listBackendNinjaOrgsResult.data?.Tenants,
- listBackendNinjaOrgsResult.isSuccess,
- ])
-
- const Offcanvas = (row, rowIndex, formatExtraData) => {
- return (
- <>
-
-
- row.haloId
- ? setHaloMappingsArray((currentHaloMappings) =>
- currentHaloMappings.filter((item) => item !== row),
- )
- : setNinjaMappingsArray((currentNinjaMappings) =>
- currentNinjaMappings.filter((item) => item !== row),
- )
- }
- >
-
-
-
- >
- )
- }
- const halocolumns = [
- {
- name: 'Tenant',
- selector: (row) => row.Tenant?.displayName,
- sortable: true,
- cell: (row) => CellTip(row.Tenant?.displayName),
- exportSelector: 'Tenant',
- },
- {
- name: 'TenantId',
- selector: (row) => row.Tenant?.customerId,
- sortable: true,
- exportSelector: 'Tenant/customerId',
- omit: true,
- },
- {
- name: 'Halo Client Name',
- selector: (row) => row['haloName'],
- sortable: true,
- cell: (row) => CellTip(row['haloName']),
- exportSelector: 'haloName',
- },
- {
- name: 'Halo ID',
- selector: (row) => row['haloId'],
- sortable: true,
- cell: (row) => CellTip(row['haloId']),
- exportSelector: 'haloId',
- },
- {
- name: 'Actions',
- cell: Offcanvas,
- maxWidth: '80px',
- },
- ]
-
- const ninjacolumns = [
- {
- name: 'Tenant',
- selector: (row) => row.Tenant?.displayName,
- sortable: true,
- cell: (row) => CellTip(row.Tenant?.displayName),
- exportSelector: 'Tenant',
- },
- {
- name: 'TenantId',
- selector: (row) => row.Tenant?.customerId,
- sortable: true,
- exportSelector: 'Tenant/customerId',
- omit: true,
- },
- {
- name: 'NinjaOne Organization Name',
- selector: (row) => row['ninjaName'],
- sortable: true,
- cell: (row) => CellTip(row['ninjaName']),
- exportSelector: 'ninjaName',
- },
- {
- name: 'NinjaOne Organization ID',
- selector: (row) => row['ninjaId'],
- sortable: true,
- cell: (row) => CellTip(row['ninjaId']),
- exportSelector: 'ninjaId',
- },
- {
- name: 'Actions',
- cell: Offcanvas,
- maxWidth: '80px',
- },
- ]
-
- return (
-
- {type === 'HaloPSA' && (
- <>
- {listBackendHaloResult.isUninitialized &&
- listHaloBackend({ path: 'api/ExecExtensionMapping?List=Halo' })}
-
-
-
- {extensionHaloConfigResult.isFetching && (
-
- )}
- Save Mappings
-
- onHaloAutomap()} className="me-2">
- {extensionNinjaOrgsAutomapResult.isFetching && (
-
- )}
- Automap HaloPSA Clients
-
- >
- }
- >
- {listBackendHaloResult.isFetching && listBackendHaloResult.isUninitialized ? (
-
- ) : (
-
- >
- )}
- {type === 'NinjaOne' && (
- <>
- {listBackendNinjaOrgsResult.isUninitialized &&
- listNinjaOrgsBackend({ path: 'api/ExecExtensionMapping?List=NinjaOrgs' })}
- {listBackendNinjaFieldsResult.isUninitialized &&
- listNinjaFieldsBackend({ path: 'api/ExecExtensionMapping?List=NinjaFields' })}
-
-
- {extensionNinjaOrgsConfigResult.isFetching && (
-
- )}
- Set Mappings
-
- onNinjaOrgsAutomap()} className="me-2">
- {extensionNinjaOrgsAutomapResult.isFetching && (
-
- )}
- Automap NinjaOne Organizations
-
- >
- }
- >
- {listBackendNinjaOrgsResult.isFetching && listBackendNinjaOrgsResult.isUninitialized ? (
-
- ) : (
-
- >
- )}
- {type === 'NinjaOne' && (
-
- {extensionNinjaFieldsConfigResult.isFetching && (
-
- )}
- Set Mappings
-
- }
- >
- {listBackendNinjaFieldsResult.isFetching ? (
-
- ) : (
-
- )}
-
- )
-}
diff --git a/src/views/email-exchange/administration/EditMailboxPermissions.jsx b/src/views/email-exchange/administration/EditMailboxPermissions.jsx
deleted file mode 100644
index 3f16a1e389d9..000000000000
--- a/src/views/email-exchange/administration/EditMailboxPermissions.jsx
+++ /dev/null
@@ -1,1017 +0,0 @@
-import React, { useEffect, useRef, useState } from 'react'
-import {
- CButton,
- CCallout,
- CCard,
- CCardBody,
- CCardHeader,
- CCardTitle,
- CCol,
- CNav,
- CNavItem,
- CTabContent,
- CTabPane,
- CForm,
- CRow,
- CSpinner,
-} from '@coreui/react'
-import useQuery from 'src/hooks/useQuery'
-import { useDispatch } from 'react-redux'
-import { Form, Field } from 'react-final-form'
-import { RFFSelectSearch, RFFCFormCheck, RFFCFormInput, RFFCFormSwitch } from 'src/components/forms'
-import { CippLazy, ModalService } from 'src/components/utilities'
-import {
- useLazyGenericPostRequestQuery,
- useLazyGenericGetRequestQuery,
- useGenericGetRequestQuery,
-} from 'src/store/api/app'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
-import { useListMailboxDetailsQuery, useListMailboxPermissionsQuery } from 'src/store/api/mailbox'
-import { CellBoolean, CippDatatable } from 'src/components/tables'
-import DatePicker from 'react-datepicker'
-import 'react-datepicker/dist/react-datepicker.css'
-import PropTypes from 'prop-types'
-
-const formatter = (cell, warning = false, reverse = false, colourless = false) =>
- CellBoolean({ cell, warning, reverse, colourless })
-
-const MailboxSettings = () => {
- const dispatch = useDispatch()
- let query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
- const [active, setActive] = useState(1)
- const columnsCal = [
- {
- name: 'User',
- selector: (row) => row['User'],
- sortable: true,
- wrap: true,
- cell: (row) => row['User'],
- exportSelector: 'User',
- maxWidth: '150px',
- },
- {
- name: 'AccessRights',
- selector: (row) => row['AccessRights'],
- sortable: true,
- wrap: true,
- cell: (row) => row['AccessRights'],
- exportSelector: 'AccessRights',
- maxWidth: '150px',
- },
- {
- name: 'Identity',
- selector: (row) => row['Identity'],
- sortable: true,
- wrap: true,
- cell: (row) => row['Identity'],
- exportSelector: 'Identity',
- maxWidth: '150px',
- },
- ]
- const columns = [
- {
- name: 'User',
- selector: (row) => row.User,
- sortable: true,
- wrap: true,
- exportSelector: 'User',
- },
- {
- name: 'Permissions',
- selector: (row) => row['Permissions'],
- sortable: true,
- wrap: true,
- exportSelector: 'Permissions',
- },
- ]
-
- return (
-
-
-
-
-
- setActive(1)} href="#">
- Mailbox Permissions
-
- setActive(2)} href="#">
- Calendar Permissions
-
- setActive(3)} href="#">
- Mailbox Forwarding
-
- setActive(4)} href="#">
- Out Of Office
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Account Information - {userId}
-
-
- {active === 1 && (
-
- )}
- {active === 2 && (
-
- )}
- {active === 3 && (
- <>
-
- >
- )}
- {active === 4 && (
- <>
-
- >
- )}
-
-
-
-
- )
-}
-
-export default MailboxSettings
-
-const MailboxPermissions = () => {
- const dispatch = useDispatch()
- let query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
-
- const [queryError, setQueryError] = useState(false)
-
- //const [EditMailboxPermission, { error: EditMailboxPermissionError, isFetching: EditMailboxPermissionIsFetching }] = useEditMailboxPermissionMutation()
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
-
- const {
- data: users = [],
- isFetching: usersIsFetching,
- error: usersError,
- } = useGenericGetRequestQuery({
- path: '/api/ListGraphRequest',
- params: {
- Endpoint: 'users',
- TenantFilter: tenantDomain,
- $filter: 'assignedLicenses/$count ne 0 and accountEnabled eq true',
- $count: true,
- },
- })
-
- useEffect(() => {
- if (!userId || !tenantDomain) {
- ModalService.open({
- body: 'Error invalid request, could not load requested user.',
- title: 'Invalid Request',
- })
- setQueryError(true)
- } else {
- setQueryError(false)
- }
- }, [userId, tenantDomain, dispatch, postResults])
- const onSubmit = (values) => {
- const shippedValues = {
- userid: userId,
- tenantFilter: tenantDomain,
- AddFullAccessNoAutoMap: values.AddFullAccessNoAutoMap ? values.AddFullAccessNoAutoMap : null,
- AddFullAccess: values.AddFullAccess ? values.AddFullAccess : null,
- RemoveFullAccess: values.RemoveFullAccess ? values.RemoveFullAccess : null,
- AddSendAs: values.AddSendAs ? values.AddSendAs : null,
- RemoveSendAs: values.RemoveSendAs ? values.RemoveSendAs : null,
- AddSendOnBehalf: values.AddSendOnBehalf ? values.AddSendOnBehalf : null,
- RemoveSendOnBehalf: values.RemoveSendOnBehalf ? values.RemoveSendOnBehalf : null,
- }
- //window.alert(JSON.stringify(shippedValues))
- genericPostRequest({ path: '/api/ExecEditMailboxPermissions', values: shippedValues })
- }
-
- const formDisabled = queryError === true
-
- return (
- <>
- {!queryError && (
- <>
- {queryError && (
-
-
-
- {/* @todo add more descriptive help message here */}
- Failed to load user
-
-
-
- )}
-
- {usersIsFetching && }
- {!usersIsFetching && (
-
- >
- )}
- >
- )
-}
-
-const CalendarPermissions = () => {
- const dispatch = useDispatch()
- let query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
-
- const [queryError, setQueryError] = useState(false)
-
- const {
- data: user = [],
- isFetching: userIsFetching,
- error: userError,
- } = useGenericGetRequestQuery({
- path: '/api/ListCalendarPermissions',
- params: { TenantFilter: tenantDomain, UserId: userId },
- })
-
- const {
- data: users = [],
- isFetching: usersIsFetching,
- error: usersError,
- } = useGenericGetRequestQuery({
- path: '/api/ListMailboxes',
- params: { TenantFilter: tenantDomain, SkipLicense: true },
- })
-
- useEffect(() => {
- if (!userId || !tenantDomain) {
- ModalService.open({
- body: 'Error invalid request, could not load requested user.',
- title: 'Invalid Request',
- })
- setQueryError(true)
- } else {
- setQueryError(false)
- }
- }, [userId, tenantDomain, dispatch])
- const [genericPostRequest, postResults] = useLazyGenericGetRequestQuery()
- const onSubmit = (values) => {
- const shippedValues = {
- FolderName: user[0].FolderName,
- userid: userId,
- tenantFilter: tenantDomain,
- Permissions: values.Permissions ? values.Permissions.value : '',
- UserToGetPermissions: values.UserToGetPermissions ? values.UserToGetPermissions.value : '',
- RemoveAccess: values.RemoveAccess ? values.RemoveAccess.value : '',
- }
- //window.alert(JSON.stringify(shippedValues))
- genericPostRequest({ path: '/api/ExecEditCalendarPermissions', params: shippedValues })
- }
- const initialState = {}
-
- // this is dumb
- const formDisabled = queryError === true
-
- const UsersMapped = users?.map((user) => ({
- value: `${user.primarySmtpAddress}`,
- name: `${user.displayName} - (${user.primarySmtpAddress})`,
- }))
- UsersMapped.unshift({ value: 'Default', name: 'Default' })
-
- return (
- <>
- {queryError && (
-
-
-
- {/* @todo add more descriptive help message here */}
- Failed to load user
-
-
-
- )}
- {!queryError && (
- <>
-
-
- {userIsFetching && }
- {userError && Error loading user }
- {!userIsFetching && (
-
-
- >
- )}
- >
- )
-}
-
-const MailboxForwarding = () => {
- const dispatch = useDispatch()
- let query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
-
- const [queryError, setQueryError] = useState(false)
-
- //const [EditMailboxPermission, { error: EditMailboxPermissionError, isFetching: EditMailboxPermissionIsFetching }] = useEditMailboxPermissionMutation()
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
-
- const {
- data: user = {},
- isFetching: userIsFetching,
- error: userError,
- } = useListMailboxPermissionsQuery({ tenantDomain, userId })
-
- const {
- data: users = [],
- isFetching: usersIsFetching,
- error: usersError,
- } = useGenericGetRequestQuery({
- path: '/api/ListGraphRequest',
- params: {
- Endpoint: 'users',
- TenantFilter: tenantDomain,
- $filter: "userType eq 'Member' and mail ge ' '", // filter out guests and users with no mailbox. #HACK "mail ne 'null'" does not work so this horrible hack is required
- },
- })
- useEffect(() => {
- if (postResults.isSuccess) {
- // @TODO do something here?
- }
- if (!userId || !tenantDomain) {
- ModalService.open({
- body: 'Error invalid request, could not load requested user.',
- title: 'Invalid Request',
- })
- setQueryError(true)
- } else {
- setQueryError(false)
- }
- }, [userId, tenantDomain, dispatch, postResults])
- const onSubmit = (values) => {
- const shippedValues = {
- userid: userId,
- tenantFilter: tenantDomain,
- ForwardInternal: values.ForwardInternal ? values.ForwardInternal : '',
- ForwardExternal: values.ForwardExternal ? values.ForwardExternal : '',
- KeepCopy: values.KeepCopy ? true : false,
- disableForwarding: values.forwardOption === 'disabled',
- }
- //window.alert(JSON.stringify(shippedValues))
- genericPostRequest({ path: '/api/ExecEmailForward', values: shippedValues })
- }
- const initialState = {
- ...user,
- }
-
- const formDisabled = queryError === true
-
- return (
- <>
- {!queryError && (
- <>
- {queryError && (
-
-
-
- {/* @todo add more descriptive help message here */}
- Failed to load user
-
-
-
- )}
-
-
- {usersIsFetching && }
- {userError && Error loading user }
- {!usersIsFetching && (
-
-
- >
- )}
- >
- )
-}
-
-const ForwardingSettings = () => {
- const query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
- const { data: details, isFetching, error } = useListMailboxDetailsQuery({ userId, tenantDomain })
- const content = [
- {
- heading: 'Forward and Deliver',
- body: formatter(details?.ForwardAndDeliver, false, false, true),
- },
- {
- heading: 'Forwarding Address',
- body: details?.ForwardingAddress ? details?.ForwardingAddress : 'N/A',
- },
- ]
-
- return (
-
- {isFetching && }
- {!isFetching && (
-
- {content.map((item, index) => (
-
-
{item.heading}
-
{item.body}
-
- ))}
-
- )}
-
- )
-}
-
-const OutOfOffice = () => {
- const dispatch = useDispatch()
- let query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
- const [queryError, setQueryError] = useState(false)
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
- const [startDate, setStartDate] = useState(new Date())
- const [endDate, setEndDate] = useState(new Date())
- const {
- data: user = {},
- isFetching: userIsFetching,
- error: userError,
- } = useListMailboxPermissionsQuery({ tenantDomain, userId })
-
- const {
- data: users = [],
- isFetching: usersIsFetching,
- error: usersError,
- } = useGenericGetRequestQuery({
- path: '/api/ListGraphRequest',
- params: {
- Endpoint: 'users',
- TenantFilter: tenantDomain,
- $filter: 'assignedLicenses/$count ne 0 and accountEnabled eq true',
- $count: true,
- },
- })
- useEffect(() => {
- if (postResults.isSuccess) {
- // @TODO do something here?
- }
- if (!userId || !tenantDomain) {
- ModalService.open({
- body: 'Error invalid request, could not load requested user.',
- title: 'Invalid Request',
- })
- setQueryError(true)
- } else {
- setQueryError(false)
- }
- }, [userId, tenantDomain, dispatch, postResults])
- const onSubmit = (values) => {
- const shippedValues = {
- user: userId,
- tenantFilter: tenantDomain,
- AutoReplyState: values.AutoReplyState ? 'Scheduled' : 'Disabled',
- StartTime: startDate.toUTCString(),
- EndTime: endDate.toUTCString(),
- InternalMessage: values.InternalMessage ? values.InternalMessage : '',
- ExternalMessage: values.ExternalMessage ? values.ExternalMessage : '',
- }
- //window.alert(JSON.stringify(shippedValues))
- genericPostRequest({ path: '/api/ExecSetOoO', values: shippedValues })
- }
- const initialState = {
- ...user,
- }
-
- const formDisabled = queryError === true
-
- return (
- <>
- {!queryError && (
- <>
- {queryError && (
-
-
-
- {/* @todo add more descriptive help message here */}
- Failed to load user
-
-
-
- )}
-
-
- {usersIsFetching && }
- {userError && Error loading user }
- {!usersIsFetching && (
-
-
- >
- )}
- >
- )
-}
-
-const OutOfOfficeSettings = () => {
- const query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
- const tenantFilter = tenantDomain
- const {
- data: details,
- isFetching,
- error,
- } = useGenericGetRequestQuery({
- path: '/api/ListOoO',
- params: { userId, tenantFilter },
- })
- const combinedRegex = /(<([^>]+)>)|| /gi
- const content = [
- {
- heading: 'Auto Reply State',
- body: formatter(details?.AutoReplyState, false, false, true),
- },
- {
- heading: 'Start Date/Time',
- body: details?.StartTime ? details?.StartTime : 'N/A',
- },
- {
- heading: 'End Date/Time',
- body: details?.EndTime ? details?.EndTime : 'N/A',
- },
- {
- heading: 'Internal Message',
- body: details?.InternalMessage ? details?.InternalMessage.replace(combinedRegex, '') : 'N/A',
- },
- {
- heading: 'External Message',
- body: details?.ExternalMessage ? details?.ExternalMessage.replace(combinedRegex, '') : 'N/A',
- },
- ]
- return (
-
- {isFetching && (
-
- Loading
-
- )}
- {!isFetching && (
-
- {content.map((item, index) => (
-
-
{item.heading}
-
{item.body}
-
- ))}
-
- )}
- {error && Could not connect to API: {error.message} }
-
- )
-}
diff --git a/src/views/email-exchange/administration/MailboxRuleList.jsx b/src/views/email-exchange/administration/MailboxRuleList.jsx
deleted file mode 100644
index 34f3798900d8..000000000000
--- a/src/views/email-exchange/administration/MailboxRuleList.jsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import React from 'react'
-import { useSelector } from 'react-redux'
-import { CippPageList } from 'src/components/layout'
-import { CellTip } from 'src/components/tables'
-import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat'
-
-const MailboxRuleList = () => {
- const tenant = useSelector((state) => state.app.currentTenant)
-
- const columns = [
- {
- selector: (row) => row?.Tenant,
- name: 'Tenant',
- sortable: true,
- exportSelector: 'Tenant',
- maxWidth: '150px',
- cell: cellGenericFormatter(),
- },
- {
- selector: (row) => row?.UserPrincipalName,
- name: 'User Principal Name',
- sortable: true,
- exportSelector: 'UserPrincipalName',
- maxWidth: '200px',
- cell: cellGenericFormatter(),
- },
- {
- selector: (row) => row?.Enabled,
- name: 'Enabled',
- sortable: true,
- cell: cellGenericFormatter(),
- exportSelector: 'Enabled',
- maxWidth: '50px',
- },
- {
- selector: (row) => row?.Name,
- name: 'Display Name',
- sortable: true,
- cell: cellGenericFormatter(),
- maxWidth: '200px',
- exportSelector: 'Name',
- },
- {
- selector: (row) => row?.Description,
- name: 'Description',
- sortable: true,
- cell: cellGenericFormatter(),
- exportSelector: 'Description',
- },
- {
- selector: (row) => row?.MailboxOwnerId,
- name: 'Mailbox',
- sortable: true,
- exportSelector: 'MailboxOwnerId',
- maxWidth: '150px',
- cell: cellGenericFormatter(),
- },
- {
- selector: (row) => row?.ForwardTo,
- name: 'Forwards To',
- sortable: true,
- exportSelector: 'ForwardTo',
- cell: cellGenericFormatter(),
- },
- ]
-
- return (
-
- )
-}
-
-export default MailboxRuleList
diff --git a/src/views/email-exchange/administration/QuarantineList.jsx b/src/views/email-exchange/administration/QuarantineList.jsx
deleted file mode 100644
index 6c5de828afec..000000000000
--- a/src/views/email-exchange/administration/QuarantineList.jsx
+++ /dev/null
@@ -1,189 +0,0 @@
-import React, { useState } from 'react'
-import { useSelector } from 'react-redux'
-import { CippPageList } from 'src/components/layout'
-import { CButton } from '@coreui/react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faEllipsisV, faMinusCircle, faPaperPlane } from '@fortawesome/free-solid-svg-icons'
-import { CippActionsOffcanvas } from 'src/components/utilities'
-import { cellDateFormatter, CellTip } from 'src/components/tables'
-
-const QuarantineList = () => {
- const tenant = useSelector((state) => state.app.currentTenant)
-
- const Offcanvas = (row, rowIndex, formatExtraData) => {
- const [ocVisible, setOCVisible] = useState(false)
- return (
- <>
- setOCVisible(true)}>
-
-
- ,
- },
- {
- label: 'Deny',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecQuarantineManagement?TenantFilter=${tenant.defaultDomainName}&ID=${row.Identity}&Type=Deny`,
- modalMessage: 'Are you sure you want to deny this message?',
- icon: ,
- },
- {
- label: 'Release & Allow Sender',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecQuarantineManagement?TenantFilter=${tenant.defaultDomainName}&ID=${row.Identity}&Type=Release&AllowSender=true`,
- modalMessage:
- 'Are you sure you want to release this email, and add the sender to the whitelist?',
- icon: ,
- },
- ]}
- placement="end"
- visible={ocVisible}
- id={row.id}
- hideFunction={() => setOCVisible(false)}
- />
- >
- )
- }
-
- //TODO: Add CellBoolean
- const columns = [
- {
- selector: (row) => row['SenderAddress'],
- name: 'Sender',
- sortable: true,
- cell: (row) => CellTip(row['SenderAddress']),
- exportSelector: 'SenderAddress',
- },
- {
- selector: (row) => row.RecipientAddress.join(', '),
- name: 'Recipient',
- sortable: true,
- exportSelector: 'RecipientAddress',
- cell: (row) => CellTip(row.RecipientAddress.join(', ')),
- },
- {
- selector: (row) => row['Subject'],
- name: 'Subject',
- sortable: true,
- cell: (row) => CellTip(row['Subject']),
- exportSelector: 'Subject',
- maxWidth: '300px',
- },
- {
- selector: (row) => row['Type'],
- name: 'Reason',
- sortable: true,
- exportSelector: 'Type',
- maxWidth: '200px',
- },
- {
- selector: (row) => row['ReceivedTime'],
- name: 'Received on',
- sortable: true,
- exportSelector: 'ReceivedTime',
- maxWidth: '150px',
- cell: cellDateFormatter(),
- },
- {
- selector: (row) => row['ReleaseStatus'],
- name: 'Status',
- sortable: true,
- exportSelector: 'ReleaseStatus',
- maxWidth: '150px',
- },
- {
- selector: (row) => row['PolicyName'],
- name: 'Blocked by Policy',
- sortable: true,
- exportSelector: 'PolicyName',
- maxWidth: '170px',
- cell: (row) => CellTip(row['PolicyName']),
- },
- {
- name: 'Actions',
- cell: Offcanvas,
- maxWidth: '100px',
- },
- ]
-
- return (
-
- )
-}
-
-export default QuarantineList
diff --git a/src/views/email-exchange/tools/MessageViewer.jsx b/src/views/email-exchange/tools/MessageViewer.jsx
deleted file mode 100644
index f010c0b37c4f..000000000000
--- a/src/views/email-exchange/tools/MessageViewer.jsx
+++ /dev/null
@@ -1,342 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react'
-import PropTypes from 'prop-types'
-import { CippPage, CippMasonry, CippMasonryItem, CippContentCard } from 'src/components/layout'
-import { parseEml, readEml, GBKUTF8, decode } from 'eml-parse-js'
-import { useMediaPredicate } from 'react-media-hook'
-import { useSelector } from 'react-redux'
-import { CellDate } from 'src/components/tables'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import {
- CButton,
- CCard,
- CCardBody,
- CCol,
- CDropdown,
- CDropdownMenu,
- CDropdownToggle,
- CLink,
- CRow,
-} from '@coreui/react'
-import ReactTimeAgo from 'react-time-ago'
-import { CippCodeBlock, ModalService } from 'src/components/utilities'
-import DOMPurify from 'dompurify'
-import ReactHtmlParser from 'react-html-parser'
-import CippDropzone from 'src/components/utilities/CippDropzone'
-
-const MessageViewer = ({ emailSource }) => {
- const [emlContent, setEmlContent] = useState(null)
- const [emlError, setEmlError] = useState(false)
- const [messageHtml, setMessageHtml] = useState('')
- const [emlHeaders, setEmlHeaders] = useState(null)
-
- const getAttachmentIcon = (contentType) => {
- if (contentType.includes('image')) {
- return 'image'
- } else if (contentType.includes('audio')) {
- return 'volume-up'
- } else if (contentType.includes('video')) {
- return 'video'
- } else if (contentType.includes('text')) {
- return 'file-lines'
- } else if (contentType.includes('pdf')) {
- return 'file-pdf'
- } else if (
- contentType.includes('zip') ||
- contentType.includes('compressed') ||
- contentType.includes('tar') ||
- contentType.includes('gzip')
- ) {
- return 'file-zipper'
- } else if (contentType.includes('msword')) {
- return 'file-word'
- } else if (contentType.includes('spreadsheet')) {
- return 'file-excel'
- } else if (contentType.includes('presentation')) {
- return 'file-powerpoint'
- } else if (contentType.includes('json') || contentType.includes('xml')) {
- return 'file-code'
- } else if (contentType.includes('rfc822')) {
- return 'envelope'
- } else {
- return 'file'
- }
- }
-
- const downloadAttachment = (attachment, newTab = false) => {
- var contentType = attachment?.contentType?.split(';')[0] ?? 'text/plain'
- var fileBytes = attachment.data
- if (fileBytes instanceof Uint8Array && attachment?.data64) {
- fileBytes = new Uint8Array(
- atob(attachment.data64)
- .split('')
- .map((c) => c.charCodeAt(0)),
- )
- }
- var fileName = attachment.name
- const blob = new Blob([fileBytes], { type: contentType ?? 'application/octet-stream' })
- const url = URL.createObjectURL(blob)
- const link = document.createElement('a')
- if (newTab) {
- if (contentType.includes('rfc822')) {
- var content = fileBytes
- const nestedMessage =
- ModalService.open({
- body: nestedMessage,
- title: fileName,
- size: 'lg',
- })
- } else if (contentType.includes('pdf')) {
- const embeddedPdf =
- ModalService.open({
- body: embeddedPdf,
- title: fileName,
- size: 'lg',
- })
- } else if (contentType.includes('image')) {
- const embeddedImage =
- ModalService.open({
- body: embeddedImage,
- title: fileName,
- size: 'lg',
- })
- } else if (contentType.includes('text')) {
- const textContent = fileBytes
- ModalService.open({
- data: textContent,
- componentType: 'codeblock',
- title: fileName,
- size: 'lg',
- })
- setTimeout(() => {
- URL.revokeObjectURL(url)
- }, 1000)
- } else {
- const newWindow = window.open()
- newWindow.location.href = url
- URL.revokeObjectURL(url)
- }
- } else {
- link.href = url
- link.download = fileName
- link.click()
- URL.revokeObjectURL(url)
- }
- }
-
- function isValidDate(d) {
- return d instanceof Date && !isNaN(d)
- }
-
- const showEmailModal = (emailSource, title = 'Email Source') => {
- ModalService.open({
- data: emailSource,
- componentType: 'codeblock',
- title: title,
- size: 'lg',
- })
- }
-
- const EmailButtons = (emailHeaders, emailSource) => {
- const emailSourceBytes = new TextEncoder().encode(emailSource)
- const blob = new Blob([emailSourceBytes], { type: 'message/rfc822' })
- const url = URL.createObjectURL(blob)
- return (
-
- {emailHeaders && (
- showEmailModal(emailHeaders, 'Email Headers')} className="me-2">
-
- View Headers
-
- )}
- showEmailModal(emailSource)}>
-
- View Source
-
-
- )
- }
-
- useEffect(() => {
- readEml(emailSource, (err, ReadEmlJson) => {
- if (err) {
- setEmlError(true)
- setEmlContent(null)
- setMessageHtml(null)
- setEmlHeaders(null)
- } else {
- setEmlContent(ReadEmlJson)
- setEmlError(false)
- if (ReadEmlJson.html) {
- var sanitizedHtml = DOMPurify.sanitize(ReadEmlJson.html)
- var parsedHtml = ReactHtmlParser(sanitizedHtml)
- setMessageHtml(parsedHtml)
- } else {
- setMessageHtml(null)
- }
- const header_regex = /(?:^[\w-]+:\s?.*(?:\r?\n[ \t].*)*\r?\n?)+/gm
- const headers = emailSource.match(header_regex)
- setEmlHeaders(headers ? headers[0] : null)
- }
- })
- }, [emailSource, setMessageHtml, setEmlError, setEmlContent, setEmlHeaders])
-
- var buttons = EmailButtons(emlHeaders, emailSource)
-
- return (
- <>
- {emlError && (
-
- Unable to parse the EML file, email source is displayed below.
-
-
- )}
-
- {emlContent && (
- <>
-
- <>
-
-
-
-
- {emlContent?.from?.name} <{emlContent?.from?.email}>
-
- {emlContent?.to?.length > 0 && (
-
-
- To: {' '}
- {emlContent?.to?.map((to) => to.name + ' <' + to.email + '>').join(', ')}
-
-
- )}
- {emlContent?.cc?.length > 0 && (
-
-
- CC: {' '}
- {emlContent?.cc?.map((cc) => cc.name + ' <' + cc.email + '>').join(', ')}
-
-
- )}
-
-
-
-
-
- {emlContent.date && isValidDate(emlContent.date)
- ? emlContent.date.toLocaleDateString()
- : 'Invalid Date'}
-
- {emlContent.date && isValidDate(emlContent.date) && (
- <>
- ( )
- >
- )}
-
-
-
-
- >
-
- {emlContent.attachments && emlContent.attachments.length > 0 && (
-
-
- {emlContent.attachments.map((attachment, index) => (
-
-
-
- {attachment.name ?? 'No name'}
-
-
- downloadAttachment(attachment)}
- >
-
- Download
-
- {(attachment?.contentType === undefined ||
- attachment?.contentType?.includes('text') ||
- attachment?.contentType?.includes('pdf') ||
- attachment?.contentType?.includes('image') ||
- attachment?.contentType?.includes('rfc822')) && (
- downloadAttachment(attachment, true)}
- >
-
- View
-
- )}
-
-
- ))}
-
-
- )}
-
- {(emlContent?.text || emlContent?.html) && (
-
-
- {messageHtml ? (
- {messageHtml}
- ) : (
-
-
-
- )}
-
-
- )}
-
- >
- )}
- >
- )
-}
-
-MessageViewer.propTypes = {
- emailSource: PropTypes.string,
-}
-
-const MessageViewerPage = () => {
- const [emlFile, setEmlFile] = useState(null)
- const onDrop = useCallback((acceptedFiles) => {
- acceptedFiles.forEach((file) => {
- const reader = new FileReader()
- reader.onabort = () => console.log('file reading was aborted')
- reader.onerror = () => console.log('file reading has failed')
- reader.onload = () => {
- setEmlFile(reader.result)
- }
- reader.readAsText(file)
- })
- }, [])
-
- return (
-
-
- {emlFile && }
-
- )
-}
-
-export default MessageViewerPage
diff --git a/src/views/email-exchange/transport/TransportRules.jsx b/src/views/email-exchange/transport/TransportRules.jsx
deleted file mode 100644
index 9d534e17dee5..000000000000
--- a/src/views/email-exchange/transport/TransportRules.jsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { CButton } from '@coreui/react'
-import { faBan, faBook, faCheck, faEllipsisV, faTrash } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import React, { useState } from 'react'
-import { useSelector } from 'react-redux'
-import { CippPageList } from 'src/components/layout'
-import { CippActionsOffcanvas } from 'src/components/utilities'
-import { CellTip } from 'src/components/tables'
-import { TitleButton } from 'src/components/buttons'
-
-const Offcanvas = (row, rowIndex, formatExtraData) => {
- const tenant = useSelector((state) => state.app.currentTenant)
- const [ocVisible, setOCVisible] = useState(false)
- //console.log(row)
- return (
- <>
- setOCVisible(true)}>
-
-
- ,
- modalBody: row,
- modalType: 'POST',
- modalUrl: `/api/AddTransportTemplate`,
- modalMessage: 'Are you sure you want to create a template based on this rule?',
- },
- {
- label: 'Enable Rule',
- color: 'info',
- icon: ,
- modal: true,
- modalUrl: `/api/EditTransportRule?State=Enable&TenantFilter=${tenant.defaultDomainName}&GUID=${row.Guid}`,
- modalMessage: 'Are you sure you want to enable this rule?',
- },
- {
- label: 'Disable Rule',
- color: 'info',
- icon: ,
- modal: true,
- modalUrl: `/api/EditTransportRule?State=Disable&TenantFilter=${tenant.defaultDomainName}&GUID=${row.Guid}`,
- modalMessage: 'Are you sure you want to disable this rule?',
- },
- {
- label: 'Delete Rule',
- color: 'danger',
- modal: true,
- icon: ,
- modalUrl: `/api/RemoveTransportRule?TenantFilter=${tenant.defaultDomainName}&GUID=${row.Guid}`,
- modalMessage: 'Are you sure you want to disable this rule?',
- },
- ]}
- placement="end"
- visible={ocVisible}
- id={row.id}
- hideFunction={() => setOCVisible(false)}
- />
- >
- )
-}
-
-const columns = [
- {
- name: 'Name',
- selector: (row) => row['Name'],
- sortable: true,
- wrap: true,
- cell: (row) => CellTip(row['Name']),
- exportSelector: 'Name',
- },
- {
- name: 'State',
- selector: (row) => row['State'],
- sortable: true,
- exportSelector: 'State',
- },
- {
- name: 'Mode',
- selector: (row) => row['Mode'],
- sortable: true,
- exportSelector: 'Mode',
- },
- {
- name: 'Error Action',
- selector: (row) => row['RuleErrorAction'],
- sortable: true,
- exportSelector: 'RuleErrorAction',
- },
- {
- name: 'description',
- selector: (row) => row['Description'],
- omit: true,
- exportSelector: 'Description',
- },
- {
- name: 'GUID',
- selector: (row) => row['Guid'],
- omit: true,
- exportSelector: 'Guid',
- },
- {
- name: 'Actions',
- cell: Offcanvas,
- maxWidth: '80px',
- },
-]
-
-const TransportRulesList = () => {
- const tenant = useSelector((state) => state.app.currentTenant)
-
- return (
-
-
- >
- }
- 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 },
- columns,
- }}
- />
- )
-}
-
-export default TransportRulesList
diff --git a/src/views/endpoint/applications/ApplicationsAddRMM.jsx b/src/views/endpoint/applications/ApplicationsAddRMM.jsx
deleted file mode 100644
index a6583e00fd4c..000000000000
--- a/src/views/endpoint/applications/ApplicationsAddRMM.jsx
+++ /dev/null
@@ -1,366 +0,0 @@
-import React from 'react'
-import { CCol, CRow, CForm, CCallout, CSpinner } from '@coreui/react'
-import { Field, FormSpy } from 'react-final-form'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faExclamationTriangle } 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, RFFCFormInput, RFFCFormRadio, RFFSelectSearch } from 'src/components/forms'
-import { useLazyGenericPostRequestQuery } from 'src/store/api/app'
-
-const Error = ({ name }) => (
-
- touched && error ? (
-
-
- {error}
-
- ) : null
- }
- />
-)
-
-Error.propTypes = {
- name: PropTypes.string.isRequired,
-}
-
-const requiredArray = (value) => (value && value.length !== 0 ? undefined : 'Required')
-
-const AddRMM = () => {
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
-
- const handleSubmit = async (values) => {
- values.selectedTenants.map(
- (tenant) => (values[`Select_${tenant.defaultDomainName}`] = tenant.defaultDomainName),
- )
- if (values.AssignTo === 'customGroup') {
- values.AssignTo = values.customGroup
- }
- genericPostRequest({ path: '/api/AddMSPApp', values: values })
- }
-
- const formValues = {
- arch: true,
- RemoveVersions: true,
- AcceptLicense: true,
- AssignTo: 'On',
- }
-
- 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
- Supply the app information
-
-
-
-
-
-
-
-
-
-
-
-
- {/* eslint-disable react/prop-types */}
- {(props) => {
- return (
- <>
-
-
-
-
-
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
-
-
-
-
-
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
-
-
-
-
-
-
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
-
-
- {props.values.selectedTenants.map((item, index) => (
-
-
-
- ))}
-
- >
- )
- }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Step 3
- Confirm and apply
-
-
- {!postResults.isSuccess && (
-
- {(props) => {
- return (
- <>
-
-
-
-
- >
- )
- }}
-
- )}
- {postResults.isFetching && (
-
- Loading
-
- )}
- {postResults.isSuccess && {postResults.data.Results} }
-
-
-
- )
-}
-
-export default AddRMM
diff --git a/src/views/endpoint/applications/ListApplicationQueue.jsx b/src/views/endpoint/applications/ListApplicationQueue.jsx
deleted file mode 100644
index 53f1e9197d33..000000000000
--- a/src/views/endpoint/applications/ListApplicationQueue.jsx
+++ /dev/null
@@ -1,139 +0,0 @@
-import React from 'react'
-import { useSelector } from 'react-redux'
-import { CSpinner, CButton, CCallout } from '@coreui/react'
-import { faCheck, faExclamationTriangle, faTrash } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { CippPageList } from 'src/components/layout'
-import { ModalService } from 'src/components/utilities'
-import { useLazyGenericGetRequestQuery } from 'src/store/api/app'
-import { CellTip } from 'src/components/tables'
-
-const RefreshAction = () => {
- const [execStandards, execStandardsResults] = useLazyGenericGetRequestQuery()
-
- const showModal = () =>
- ModalService.confirm({
- body: (
-
- Deploy all queued applications to tenants?
-
- Please note: This job runs automatically every 12 hours.
-
- ),
- onConfirm: () => execStandards({ path: 'api/AddChocoApp_OrchestrationStarter' }),
- })
-
- return (
- <>
- {execStandardsResults.data?.Results ===
- 'Already running. Please wait for the current instance to finish' && (
- {execStandardsResults.data?.Results}
- )}
-
- {execStandardsResults.isLoading && }
- {execStandardsResults.error && (
-
- )}
- {execStandardsResults.isSuccess && }
- Deploy now
-
- >
- )
-}
-const ListApplicationQueue = () => {
- const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery()
- const Actions = (row, index, column) => {
- const handleDeleteStandard = (apiurl, message) => {
- ModalService.confirm({
- title: 'Confirm',
- body: {message}
,
- onConfirm: () => ExecuteGetRequest({ path: apiurl }),
- confirmLabel: 'Continue',
- cancelLabel: 'Cancel',
- })
- }
- return (
-
- handleDeleteStandard(
- `api/RemoveQueuedApp?ID=${row.id}`,
- 'Do you want to delete the queued application?',
- )
- }
- >
-
-
- )
- }
- const columns = [
- {
- name: 'Tenant',
- selector: (row) => row['tenantName'],
- sortable: true,
- cell: (row) => CellTip(row['tenantName']),
- exportSelector: 'tenantName',
- minWidth: '200px',
- },
- {
- name: 'Application Name',
- selector: (row) => row['applicationName'],
- sortable: true,
- cell: (row) => CellTip(row['applicationName']),
- exportSelector: 'applicationName',
- minWidth: '200px',
- },
- {
- name: 'Install command',
- selector: (row) => row['cmdLine'],
- sortable: true,
- cell: (row) => CellTip(row['cmdLine']),
- exportSelector: 'cmdLine',
- },
- {
- name: 'Assign To',
- selector: (row) => row['assignTo'],
- sortable: true,
- cell: (row) => CellTip(row['assignTo']),
- exportSelector: 'assignTo',
- },
- {
- name: 'Actions',
- cell: Actions,
- },
- ]
- const tenant = useSelector((state) => state.app.currentTenant)
-
- return (
-
- {getResults.isFetching && (
-
- Loading
-
- )}
- {getResults.isSuccess && {getResults.data?.Results} }
- {getResults.isError && (
- Could not connect to API: {getResults.error.message}
- )}
- ],
- },
- keyField: 'id',
- columns,
- reportName: `ApplicationQueue-List`,
- path: '/api/ListApplicationQueue',
- params: { TenantFilter: tenant?.defaultDomainName },
- }}
- />
-
- )
-}
-
-export default ListApplicationQueue
diff --git a/src/views/endpoint/intune/MEMListCompliance.jsx b/src/views/endpoint/intune/MEMListCompliance.jsx
deleted file mode 100644
index 328a387566fd..000000000000
--- a/src/views/endpoint/intune/MEMListCompliance.jsx
+++ /dev/null
@@ -1,163 +0,0 @@
-import React, { useState } from 'react'
-import { useSelector } from 'react-redux'
-import { CButton } from '@coreui/react'
-import {
- faBook,
- faEdit,
- faEllipsisV,
- faGlobeEurope,
- faPager,
- faTrashAlt,
- faUser,
-} from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { CippPageList } from 'src/components/layout'
-import { Link } from 'react-router-dom'
-import { CippActionsOffcanvas, CippCodeBlock } from 'src/components/utilities'
-import { TitleButton } from 'src/components/buttons'
-import { cellBooleanFormatter, cellDateFormatter } from 'src/components/tables'
-
-const Actions = (row, rowIndex, formatExtraData) => {
- const [ocVisible, setOCVisible] = useState(false)
- const tenant = useSelector((state) => state.app.currentTenant)
- return (
- <>
- setOCVisible(true)}>
-
-
- ,
- modalUrl: `/api/AddIntuneTemplate?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&URLName=deviceCompliancePolicies`,
- modalMessage: 'Are you sure you want to create a template based on this policy?',
- },
- {
- icon: ,
- label: ' Assign to All Users',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecAssignPolicy?AssignTo=allLicensedUsers&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&type=deviceCompliancePolicies`,
- modalMessage: `Are you sure you want to assign ${row.displayName} to all users?`,
- },
- {
- icon: ,
- label: ' Assign to All Devices',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecAssignPolicy?AssignTo=AllDevices&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&type=deviceCompliancePolicies`,
- modalMessage: `Are you sure you want to assign ${row.displayName} to all devices?`,
- },
- {
- icon: ,
- label: ' Assign Globally (All Users / All Devices)',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecAssignPolicy?AssignTo=AllDevicesAndUsers&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&type=deviceCompliancePolicies`,
- modalMessage: `Are you sure you want to assign ${row.displayName} to all users and devices?`,
- },
- {
- label: 'Delete Policy',
- color: 'danger',
- modal: true,
- icon: ,
- modalUrl: `/api/RemovePolicy?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&URLName=deviceCompliancePolicies`,
- modalMessage: 'Are you sure you want to delete this policy?',
- },
- ]}
- placement="end"
- visible={ocVisible}
- id={row.id}
- hideFunction={() => setOCVisible(false)}
- />
- >
- )
-}
-
-const columns = [
- {
- selector: (row) => row['displayName'],
- name: 'Name',
- sortable: true,
- exportSelector: 'displayName',
- },
- {
- selector: (row) => row['description'],
- name: 'Description',
- sortable: true,
- exportSelector: 'description',
- },
- {
- selector: (row) => row['lastModifiedDateTime'],
- name: 'Last Modified',
- exportSelector: 'lastModifiedDateTime',
- cell: cellDateFormatter({ format: 'relative' }),
- },
- {
- name: 'Actions',
- cell: Actions,
- maxWidth: '80px',
- },
-]
-
-const ComplianceList = () => {
- const tenant = useSelector((state) => state.app.currentTenant)
-
- // eslint-disable-next-line react/prop-types
- const ExpandedComponent = ({ data }) => (
- // eslint-disable-next-line react/prop-types
-
- )
-
- return (
-
-
- >
- }
- tenantSelector={true}
- datatable={{
- path: '/api/ListGraphRequest',
- params: {
- TenantFilter: tenant?.defaultDomainName,
- Endpoint: 'deviceManagement/deviceCompliancePolicies',
- $orderby: 'displayName',
- $count: true,
- },
- columns,
- reportName: `${tenant?.defaultDomainName}-MEMPolicies-List`,
- tableProps: {
- expandableRows: true,
- expandableRowsComponent: ExpandedComponent,
- expandOnRowClicked: true,
- selectableRows: true,
- actionsList: [
- {
- label: 'Delete Policy',
- modal: true,
- modalUrl: `api/RemovePolicy?TenantFilter=${tenant?.defaultDomainName}&ID=!id&URLName=deviceCompliancePolicies`,
- modalMessage: 'Are you sure you want to delete these policies?',
- },
- ],
- },
- }}
- />
- )
-}
-
-export default ComplianceList
diff --git a/src/views/endpoint/intune/MEMListPolicies.jsx b/src/views/endpoint/intune/MEMListPolicies.jsx
deleted file mode 100644
index f63db28effef..000000000000
--- a/src/views/endpoint/intune/MEMListPolicies.jsx
+++ /dev/null
@@ -1,158 +0,0 @@
-import React, { useState } from 'react'
-import { useSelector } from 'react-redux'
-import { CButton } from '@coreui/react'
-import {
- faBook,
- faEdit,
- faEllipsisV,
- faGlobeEurope,
- faPager,
- faTrashAlt,
- faUser,
-} from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { CippPageList } from 'src/components/layout'
-import { Link } from 'react-router-dom'
-import { CippActionsOffcanvas, CippCodeBlock } from 'src/components/utilities'
-import { TitleButton } from 'src/components/buttons'
-
-const Actions = (row, rowIndex, formatExtraData) => {
- const [ocVisible, setOCVisible] = useState(false)
-
- const tenant = useSelector((state) => state.app.currentTenant)
- return (
- <>
- setOCVisible(true)}>
-
-
- ,
- modalUrl: `/api/AddIntuneTemplate?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&URLName=${row.URLName}`,
- modalMessage: 'Are you sure you want to create a template based on this policy?',
- },
- {
- icon: ,
- label: ' Assign to All Users',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecAssignPolicy?AssignTo=allLicensedUsers&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&type=${row.URLName}`,
- modalMessage: `Are you sure you want to assign ${row.displayName} to all users?`,
- },
- {
- icon: ,
- label: ' Assign to All Devices',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecAssignPolicy?AssignTo=AllDevices&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&type=${row.URLName}`,
- modalMessage: `Are you sure you want to assign ${row.displayName} to all devices?`,
- },
- {
- icon: ,
- label: ' Assign Globally (All Users / All Devices)',
- color: 'info',
- modal: true,
- modalUrl: `/api/ExecAssignPolicy?AssignTo=AllDevicesAndUsers&TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&type=${row.URLName}`,
- modalMessage: `Are you sure you want to assign ${row.displayName} to all users and devices?`,
- },
- {
- label: 'Delete Policy',
- color: 'danger',
- modal: true,
- icon: ,
- modalUrl: `/api/RemovePolicy?TenantFilter=${tenant.defaultDomainName}&ID=${row.id}&URLName=${row.URLName}`,
- modalMessage: 'Are you sure you want to delete this policy?',
- },
- ]}
- placement="end"
- visible={ocVisible}
- id={row.id}
- hideFunction={() => setOCVisible(false)}
- />
- >
- )
-}
-
-const columns = [
- {
- selector: (row) => row['displayName'],
- name: 'Name',
- sortable: true,
- exportSelector: 'displayName',
- },
- {
- selector: (row) => row['PolicyTypeName'],
- name: 'Profile Type',
- sortable: true,
- exportSelector: 'PolicyTypeName',
- },
- {
- selector: (row) => row['id'],
- name: 'id',
- omit: true,
- exportSelector: 'id',
- },
- {
- name: 'Actions',
- cell: Actions,
- maxWidth: '80px',
- },
-]
-
-const IntuneList = () => {
- const tenant = useSelector((state) => state.app.currentTenant)
-
- // eslint-disable-next-line react/prop-types
- const ExpandedComponent = ({ data }) => (
- // eslint-disable-next-line react/prop-types
-
- )
-
- return (
-
-
- >
- }
- tenantSelector={true}
- datatable={{
- path: '/api/ListIntunePolicy?type=ESP',
- params: { TenantFilter: tenant?.defaultDomainName },
- columns,
- reportName: `${tenant?.defaultDomainName}-MEMPolicies-List`,
- tableProps: {
- expandableRows: true,
- expandableRowsComponent: ExpandedComponent,
- expandOnRowClicked: true,
- selectableRows: true,
- actionsList: [
- {
- label: 'Delete Policy',
- modal: true,
- modalUrl: `api/RemovePolicy?TenantFilter=${tenant?.defaultDomainName}&ID=!id&URLName=!URLName`,
- modalMessage: 'Are you sure you want to delete these policies?',
- },
- ],
- },
- }}
- />
- )
-}
-
-export default IntuneList
diff --git a/src/views/identity/administration/Devices.jsx b/src/views/identity/administration/Devices.jsx
deleted file mode 100644
index 664f7552757c..000000000000
--- a/src/views/identity/administration/Devices.jsx
+++ /dev/null
@@ -1,194 +0,0 @@
-import React, { useEffect, useState } from 'react'
-import { useSelector } from 'react-redux'
-import { CellTip, cellBooleanFormatter } from 'src/components/tables'
-import { CippPageList } from 'src/components/layout'
-import { Link } from 'react-router-dom'
-import { CButton } from '@coreui/react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faEdit, faEllipsisV } from '@fortawesome/free-solid-svg-icons'
-import { CippActionsOffcanvas } from 'src/components/utilities'
-import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat'
-
-const DevicesList = () => {
- const [tenantColumnSet, setTenantColumn] = useState(true)
- const tenant = useSelector((state) => state.app.currentTenant)
- const Offcanvas = (row, rowIndex, formatExtraData) => {
- const tenant = useSelector((state) => state.app.currentTenant)
- const [ocVisible, setOCVisible] = useState(false)
- const editLink = `/identity/administration/groups/edit?groupId=${row.id}&tenantDomain=${tenant.defaultDomainName}`
- return (
- <>
- setOCVisible(true)}>
-
-
- setOCVisible(false)}
- />
- >
- )
- }
- const columns = [
- {
- name: 'Tenant',
- selector: (row) => row['Tenant'],
- sortable: true,
- cell: (row) => CellTip(row['Tenant']),
- exportSelector: 'Tenant',
- omit: tenantColumnSet,
- },
- {
- name: 'Retrieval Status',
- selector: (row) => row['CippStatus'],
- sortable: true,
- cell: (row) => CellTip(row['CippStatus']),
- exportSelector: 'CippStatus',
- omit: tenantColumnSet,
- },
- {
- selector: (row) => row['displayName'],
- name: 'Display Name',
- sortable: true,
- cell: (row) => CellTip(row['displayName']),
- exportSelector: 'displayName',
- },
- {
- selector: (row) => row['accountEnabled'],
- name: 'Enabled',
- sortable: true,
- cell: cellGenericFormatter(),
- exportSelector: 'accountEnabled',
- },
- {
- selector: (row) => row['deviceOwnership'],
- name: 'Device Ownership',
- sortable: true,
- cell: (row) => CellTip(row['deviceOwnership']),
- exportSelector: 'recipientType',
- },
- {
- selector: (row) => row['enrollmentType'],
- name: 'Enrollment Type',
- sortable: true,
- exportSelector: 'enrollmentType',
- },
- {
- selector: (row) => row['manufacturer'],
- name: 'Manufacturer',
- sortable: true,
- exportSelector: 'manufacturer',
- },
- {
- selector: (row) => row['model'],
- name: 'Model',
- sortable: true,
- exportSelector: 'model',
- },
- {
- selector: (row) => row['operatingSystem'],
- name: 'OS',
- sortable: true,
- exportSelector: 'operatingSystem',
- },
- {
- selector: (row) => row['operatingSystemVersion'],
- name: 'Version',
- sortable: true,
- exportSelector: 'operatingSystemVersion',
- },
- {
- selector: (row) => row['profileType'],
- name: 'Profile Type',
- sortable: true,
- exportSelector: 'profileType',
- },
- {
- name: 'Actions',
- cell: Offcanvas,
- maxWidth: '20px',
- },
- ]
- useEffect(() => {
- if (tenant.defaultDomainName === 'AllTenants') {
- setTenantColumn(false)
- }
- if (tenant.defaultDomainName !== 'AllTenants') {
- setTenantColumn(true)
- }
- }, [tenant.defaultDomainName, tenantColumnSet])
- return (
-
- )
-}
-
-export default DevicesList
diff --git a/src/views/identity/administration/UserMailboxRuleList.jsx b/src/views/identity/administration/UserMailboxRuleList.jsx
deleted file mode 100644
index ae2592866e85..000000000000
--- a/src/views/identity/administration/UserMailboxRuleList.jsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { CellBoolean, cellBooleanFormatter, CellTip } from 'src/components/tables'
-import { DatatableContentCard } from 'src/components/contentcards'
-import { faEnvelope } from '@fortawesome/free-solid-svg-icons'
-
-const rowStyle = (row, rowIndex) => {
- const style = {}
-
- return style
-}
-
-export default function UserMailboxRuleList({ userId, userEmail, tenantDomain, className = null }) {
- const formatter = (cell) => CellBoolean({ cell })
- const columns = [
- {
- selector: (row) => row['Name'],
- name: 'Display Name',
- sortable: true,
- cell: (row) => CellTip(row['Name']),
- exportSelector: 'Name',
- width: '200px',
- },
- {
- selector: (row) => row['Description'],
- name: 'Description',
- sortable: true,
- cell: (row) => CellTip(row['Description']),
- exportSelector: 'Description',
- width: '350px',
- },
- {
- selector: (row) => row['ForwardTo'],
- name: 'Forwards To',
- sortable: true,
- cell: (row) => CellTip(row['ForwardTo']),
- exportSelector: 'ForwardTo',
- width: '250px',
- },
- {
- selector: (row) => row['RedirectTo'],
- name: 'Redirect To',
- sortable: true,
- cell: (row) => CellTip(row['RedirectTo']),
- exportSelector: 'RedirectTo',
- maxwidth: '250px',
- },
- {
- selector: (row) => row['CopyToFolder'],
- name: 'Copy To Folder',
- sortable: true,
- cell: (row) => CellTip(row['CopyToFolder']),
- exportSelector: 'CopyToFolder',
- maxwidth: '200px',
- },
- {
- selector: (row) => row['MoveToFolder'],
- name: 'Move To Folder',
- sortable: true,
- cell: (row) => CellTip(row['MoveToFolder']),
- exportSelector: 'MoveToFolder',
- maxwidth: '200px',
- },
- {
- selector: (row) => row['DeleteMessage'],
- name: 'Delete Message',
- sortable: true,
- cell: cellBooleanFormatter({ colourless: true }),
- formatter,
- exportSelector: 'DeleteMessage',
- width: '200px',
- },
- ]
- return (
-
- )
-}
-
-UserMailboxRuleList.propTypes = {
- userId: PropTypes.string.isRequired,
- userEmail: PropTypes.string,
- tenantDomain: PropTypes.string.isRequired,
- className: PropTypes.string,
-}
diff --git a/src/views/identity/administration/ViewBEC.jsx b/src/views/identity/administration/ViewBEC.jsx
deleted file mode 100644
index 4f1173042008..000000000000
--- a/src/views/identity/administration/ViewBEC.jsx
+++ /dev/null
@@ -1,441 +0,0 @@
-import React, { useEffect } from 'react'
-import { CButton, CCallout, CLink, CCardTitle, CSpinner } from '@coreui/react'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import {
- faCheckCircle,
- faRedo,
- faTimesCircle,
- faLaptop,
- faKey,
- faForward,
- faUsers,
- faAsterisk,
- faIdBadge,
- faWindowRestore,
- faSignInAlt,
-} from '@fortawesome/free-solid-svg-icons'
-import { useLazyExecBecCheckQuery } from 'src/store/api/users'
-import useQuery from 'src/hooks/useQuery'
-import { CippTable } from 'src/components/tables'
-import { useLazyGenericPostRequestQuery } from 'src/store/api/app'
-import { CippContentCard, CippMasonry, CippMasonryItem, CippPage } from 'src/components/layout'
-import 'react-loading-skeleton/dist/skeleton.css'
-import Skeleton from 'react-loading-skeleton'
-import useConfirmModal from 'src/hooks/useConfirmModal'
-
-const ViewBec = () => {
- let query = useQuery()
- const userId = query.get('userId')
- const userName = query.get('ID')
- const tenantDomain = query.get('tenantDomain')
- const [execBecRemediate, execRemediateResults] = useLazyGenericPostRequestQuery()
- const [execBecView, results] = useLazyExecBecCheckQuery()
- const { data: alerts = {}, isFetching, error, isSuccess } = results
- useEffect(() => {
- execBecView({ tenantFilter: tenantDomain, userId: userId, userName: userName })
- }, [execBecView, tenantDomain, userId, userName])
-
- const deviceColumns = [
- {
- name: 'Device Model',
- selector: (row) => row['DeviceModel'],
- sortable: true,
- },
- {
- name: 'First Sync Time',
- selector: (row) => row['FirstSyncTime'],
- sortable: true,
- },
- {
- name: 'Device User Agent',
- selector: (row) => row['DeviceUserAgent'],
- sortable: true,
- },
- ]
-
- const rulesColumns = [
- {
- name: 'Creator IP',
- selector: (row) => row['ClientIP'],
- sortable: true,
- grow: 0,
- },
- {
- name: 'Rule Name',
- selector: (row) => row['RuleName'],
- sortable: true,
- },
- {
- name: 'Rule Conditions',
- selector: (row) => row['RuleCondition'],
- sortable: true,
- },
- {
- name: 'Created on',
- selector: (row) => row['CreationTime'],
- sortable: true,
- },
- {
- name: 'Created for',
- selector: (row) => row['UserId'],
- sortable: true,
- },
- ]
-
- const logonColumns = [
- {
- name: 'App',
- selector: (row) => row['AppDisplayName'],
- sortable: true,
- },
- {
- name: 'Date Time',
- selector: (row) => row['CreatedDateTime'],
- sortable: true,
- },
- {
- name: 'Error code',
- selector: (row) => row.id,
- sortable: true,
- },
- {
- name: 'Details',
- selector: (row) => row.Status,
- sortable: true,
- },
- {
- name: 'IP',
- selector: (row) => row.IPAddress,
- sortable: true,
- },
- ]
-
- const mailboxlogonColumns = [
- {
- name: 'IP',
- selector: (row) => row['IPAddress'],
- sortable: true,
- },
- {
- name: 'User',
- selector: (row) => row['userPrincipalName'],
- sortable: true,
- },
- {
- name: 'Application',
- selector: (row) => row['AppDisplayName'],
- sortable: true,
- },
- {
- name: 'Result',
- selector: (row) => row['Status'],
- sortable: true,
- },
- ]
- const newUserColumns = [
- {
- name: 'DisplayName',
- selector: (row) => row['displayName'],
- sortable: true,
- },
- {
- name: 'Username',
- selector: (row) => row['userPrincipalName'],
- sortable: true,
- },
- {
- name: 'Date',
- selector: (row) => row['CreatedDateTime'],
- sortable: true,
- },
- ]
-
- const passwordColumns = [
- {
- name: 'displayName',
- selector: (row) => row['displayName'],
- sortable: true,
- },
- {
- name: 'Username',
- selector: (row) => row['userPrincipalName'],
- sortable: true,
- },
- {
- name: 'Date',
- selector: (row) => row['lastPasswordChangeDateTime'],
- sortable: true,
- },
- ]
-
- const permissionColumns = [
- {
- name: 'Operation',
- selector: (row) => row['Operation'],
- sortable: true,
- },
- {
- name: 'Executed by',
- selector: (row) => row['UserKey'],
- sortable: true,
- },
- {
- name: 'Executed on',
- selector: (row) => row['ObjectId'],
- sortable: true,
- },
- {
- name: 'Permissions',
- selector: (row) => row['Permissions'],
- sortable: true,
- },
- ]
-
- const appColumns = [
- {
- name: 'Type',
- selector: (row) => row['Operation'],
- sortable: true,
- },
- {
- name: 'User',
- selector: (row) => row['UserId'],
- sortable: true,
- },
- {
- name: 'Application',
- selector: (row) => row['ObjectId'],
- sortable: true,
- },
- {
- name: 'Result',
- selector: (row) => row['ResultStatus'],
- sortable: true,
- },
- ]
- const handleReMediate = useConfirmModal({
- body: Are you sure you want to remediate this user?
,
- onConfirm: () => {
- execBecRemediate({
- path: '/api/execBecRemediate',
- values: {
- userId: userId,
- tenantFilter: tenantDomain,
- userName: userName,
- },
- })
- },
- })
- return (
-
-
-
- Business Email Compromise Overview - {userName}}
- button={
-
- execBecView({
- tenantFilter: tenantDomain,
- userId: userId,
- overwrite: true,
- })
- }
- disabled={isFetching}
- >
- {!isFetching && }
- Refresh Data
-
- }
- >
-
- Loading Data: {isFetching && }
- {!isFetching && error && }
- {isSuccess && (
- <>
-
- Data has been extracted at {alerts.ExtractedAt}
- >
- )}
-
-
- Use this information as a guide to check if a tenant or e-mail address might have been
- compromised. All data is retrieved from the last 7 days of logs.
-
-
- If you need more extensive information, run the{' '}
- HAWK tool to investigate further
- if you believe this user to be compromised.
-
-
- Hit the button below to execute the following tasks:
-
Block user signin
- Reset user password
- Disconnect all current sessions
- Disable all inbox rules for the user
-
- handleReMediate()}>Remediate User
- {!execRemediateResults.isSuccess && execRemediateResults.isError && (
- Error. Could not remediate user
- )}
- {execRemediateResults.isFetching && (
-
-
-
- )}
- {execRemediateResults.isSuccess && (
-
- {execRemediateResults.data?.Results.map((item, idx) => {
- return {item}
- })}
-
- )}
-
-
-
-
- {isFetching && }
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
-
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
-
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
-
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
-
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
-
- {isSuccess && (
-
- )}
-
-
-
-
- {isFetching && }
-
- {isSuccess && (
-
- )}
-
-
-
-
- )
-}
-
-export default ViewBec
diff --git a/src/views/identity/administration/ViewUser.jsx b/src/views/identity/administration/ViewUser.jsx
deleted file mode 100644
index 72341f5cda9f..000000000000
--- a/src/views/identity/administration/ViewUser.jsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import React, { useEffect, useState } from 'react'
-import { CSpinner } from '@coreui/react'
-import PropTypes from 'prop-types'
-import useQuery from 'src/hooks/useQuery'
-import { useDispatch } from 'react-redux'
-import { CippPage, CippMasonry, CippMasonryItem } from 'src/components/layout'
-import { ModalService } from 'src/components/utilities'
-import UserDevices from 'src/views/identity/administration/UserDevices'
-import UserDetails from 'src/views/identity/administration/UserDetails'
-import UserLastLoginDetails from 'src/views/identity/administration/UserLastLoginDetails'
-import UserCAPs from 'src/views/identity/administration/UserCAPs'
-import UserActions from 'src/views/identity/administration/UserActions'
-import UserOneDriveUsage from 'src/views/identity/administration/UserOneDriveUsage'
-import User365Management from 'src/views/identity/administration/User365Management'
-import UserEmailDetails from 'src/views/identity/administration/UserEmailDetails'
-import UserEmailUsage from 'src/views/identity/administration/UserEmailUsage'
-import UserEmailSettings from 'src/views/identity/administration/UserEmailSettings'
-import UserEmailPermissions from 'src/views/identity/administration/UserEmailPermissions'
-import UserGroups from 'src/views/identity/administration/UserGroups'
-import UserSigninLogs from 'src/views/identity/administration/UserSigninLogs'
-import UserMailboxRuleList from 'src/views/identity/administration/UserMailboxRuleList'
-import { useListUserQuery } from 'src/store/api/users'
-
-const ViewUser = (props) => {
- const dispatch = useDispatch()
- let query = useQuery()
- const userId = query.get('userId')
- const tenantDomain = query.get('tenantDomain')
- const userEmail = query.get('userEmail')
- const [queryError, setQueryError] = useState(false)
-
- const {
- data: user = {},
- isFetching: userFetching,
- error: userError,
- } = useListUserQuery({ tenantDomain, userId })
-
- useEffect(() => {
- if (!userId || !tenantDomain) {
- ModalService.open({
- body: 'Error invalid request, could not load requested user.',
- title: 'Invalid Request',
- })
- setQueryError(true)
- }
- }, [tenantDomain, userId, dispatch])
-
- return (
-
- {userFetching && }
- {!userFetching && userError && Error loading user }
- {!queryError && !userFetching && (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
- )
-}
-
-ViewUser.propTypes = {
- params: PropTypes.object,
- location: PropTypes.object,
-}
-
-export default ViewUser
diff --git a/src/views/tenant/backup/CreateBackup.jsx b/src/views/tenant/backup/CreateBackup.jsx
deleted file mode 100644
index faec25e074a3..000000000000
--- a/src/views/tenant/backup/CreateBackup.jsx
+++ /dev/null
@@ -1,268 +0,0 @@
-import React, { useState } from 'react'
-import { CButton, CCallout, CCol, CForm, CRow, CSpinner, CTooltip } from '@coreui/react'
-import { useSelector } from 'react-redux'
-import { Field, Form } from 'react-final-form'
-import { RFFCFormSwitch } from 'src/components/forms'
-import {
- useGenericGetRequestQuery,
- useLazyGenericGetRequestQuery,
- useLazyGenericPostRequestQuery,
-} from 'src/store/api/app'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import { faCircleNotch, faEdit, faEye } from '@fortawesome/free-solid-svg-icons'
-import { CippPage, CippPageList } from 'src/components/layout'
-import 'react-datepicker/dist/react-datepicker.css'
-import { ModalService, TenantSelector } from 'src/components/utilities'
-import arrayMutators from 'final-form-arrays'
-import { useListConditionalAccessPoliciesQuery } from 'src/store/api/tenants'
-import CippButtonCard from 'src/components/contentcards/CippButtonCard'
-import { CellTip, cellGenericFormatter } from 'src/components/tables/CellGenericFormat'
-import { cellBadgeFormatter, cellDateFormatter } from 'src/components/tables'
-
-const CreateBackup = () => {
- const [ExecuteGetRequest, getResults] = useLazyGenericGetRequestQuery()
- const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName)
- const [refreshState, setRefreshState] = useState(false)
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
-
- const onSubmit = (values) => {
- const startDate = new Date()
- startDate.setHours(0, 0, 0, 0)
- const unixTime = Math.floor(startDate.getTime() / 1000) - 45
- const shippedValues = {
- TenantFilter: tenantDomain,
- Name: `CIPP Backup ${tenantDomain}`,
- Command: { value: `New-CIPPBackup` },
- Parameters: { backupType: 'Scheduled', ScheduledBackupValues: { ...values } },
- ScheduledTime: unixTime,
- Recurrence: { value: '1d' },
- }
- genericPostRequest({
- path: '/api/AddScheduledItem?hidden=true&DisallowDuplicateName=true',
- values: shippedValues,
- }).then((res) => {
- setRefreshState(res.requestId)
- })
- }
- const Offcanvas = (row, rowIndex, formatExtraData) => {
- 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.Results)
- } catch (error) {
- jsonResults = row.Results
- }
-
- return (
- <>
-
-
- handleDeleteSchedule(
- `/api/RemoveScheduledItem?&ID=${row.RowKey}`,
- 'Do you want to delete this job?',
- )
- }
- size="sm"
- variant="ghost"
- color="danger"
- >
-
-
-
- >
- )
- }
- const columns = [
- {
- name: 'Tenant',
- selector: (row) => row['Tenant'],
- sortable: true,
- cell: (row) => CellTip(row['Tenant']),
- exportSelector: 'Tenant',
- },
- {
- name: 'Task State',
- selector: (row) => row['TaskState'],
- sortable: true,
- cell: cellBadgeFormatter(),
- exportSelector: 'TaskState',
- },
- {
- name: 'Last executed time',
- selector: (row) => row['ExecutedTime'],
- sortable: true,
- cell: cellDateFormatter({ format: 'relative' }),
- exportSelector: 'ExecutedTime',
- },
- {
- name: 'Actions',
- cell: Offcanvas,
- maxWidth: '100px',
- },
- ]
-
- const {
- data: users = [],
- isFetching: usersIsFetching,
- error: usersError,
- } = useGenericGetRequestQuery({
- path: '/api/ListGraphRequest',
- params: {
- TenantFilter: tenantDomain,
- Endpoint: 'users',
- $select: 'id,displayName,userPrincipalName,accountEnabled',
- $count: true,
- $top: 999,
- $orderby: 'displayName',
- },
- })
-
- const {
- data: caPolicies = [],
- isFetching: caIsFetching,
- error: caError,
- } = useListConditionalAccessPoliciesQuery({ domain: tenantDomain })
-
- return (
-
- <>
-
-
-
- Create Backup Schedule
- {postResults.isFetching && (
-
- )}
-
- }
- title="Add backup Schedule"
- icon={faEdit}
- >
-
-
-
-
-
-
-
- >
-
- )
-}
-
-export default CreateBackup
diff --git a/src/views/tenant/backup/RestoreBackup.jsx b/src/views/tenant/backup/RestoreBackup.jsx
deleted file mode 100644
index e2d3d1ec9a61..000000000000
--- a/src/views/tenant/backup/RestoreBackup.jsx
+++ /dev/null
@@ -1,239 +0,0 @@
-import React, { useState } from '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'
-import { useSelector } from 'react-redux'
-import { CippCallout, CippWizard } from 'src/components/layout'
-import PropTypes from 'prop-types'
-import { Condition, RFFCFormSwitch, RFFSelectSearch } from 'src/components/forms'
-import { TenantSelector } from 'src/components/utilities'
-import { useGenericGetRequestQuery, useLazyGenericPostRequestQuery } from 'src/store/api/app'
-import 'react-datepicker/dist/react-datepicker.css'
-
-const Error = ({ name }) => (
-
- touched && error ? (
-
-
- {error}
-
- ) : null
- }
- />
-)
-
-Error.propTypes = {
- name: PropTypes.string.isRequired,
-}
-
-const OffboardingWizard = () => {
- const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName)
- const {
- data: currentBackups = [],
- isFetching: currentBackupsIsFetching,
- error: currentBackupsError,
- } = useGenericGetRequestQuery({
- path: `/api/ExecListBackup?TenantFilter=${tenantDomain}&Type=Scheduled`,
- })
-
- const [genericPostRequest, postResults] = useLazyGenericPostRequestQuery()
-
- const handleSubmit = (values) => {
- const startDate = new Date()
- const unixTime = Math.floor(startDate.getTime() / 1000) - 45
- const shippedValues = {
- TenantFilter: tenantDomain,
- Name: `CIPP Restore ${tenantDomain}`,
- Command: { value: `New-CIPPRestore` },
- Parameters: { Type: 'Scheduled', RestoreValues: { ...values } },
- ScheduledTime: unixTime,
- PostExecution: {
- Webhook: values.webhook,
- Email: values.email,
- PSA: values.psa,
- },
- }
- genericPostRequest({ path: '/api/AddScheduledItem', values: shippedValues }).then((res) => {})
- }
-
- return (
-
-
-
- Step 1
- Choose a tenant
-
-
- {(props) => }
-
-
-
-
- Step 2
- Select the backup to restore
-
-
-
- ({
- value: backup.RowKey,
- name: `${backup.RowKey}`,
- }))}
- placeholder={!currentBackupsIsFetching ? 'Select a backup' : 'Loading...'}
- name="backup"
- />
- {currentBackupsError && Failed to load list of Current Backups }
-
-
-
-
-
- Step 3
- Choose restore options
-
-
-
-
-
- Identity
-
-
- Conditional Access
-
-
-
- Intune
-
-
-
- CIPP
-
-
-
-
-
-
-
-
-
-
-
-
- Warning
-
- Overwriting existing entries will remove the current settings and replace them
- with the backup settings. If you have selected to restore users, all properties
- will be overwritten with the backup settings.
-
-
-
- To prevent and skip already existing entries, deselect the setting from the list
- above, or disable overwrite.
-
-
-
-
-
-
-
- Send Restore results to:
-
-
-
-
-
-
-
-
-
-
- Step 4
- Confirm and apply
-
-
-
- {postResults.isFetching && (
-
- Loading
-
- )}
- {postResults.isSuccess && {postResults.data.Results} }
- {!postResults.isSuccess && (
-
- {/* eslint-disable react/prop-types */}
- {(props) => (
- <>
-
-
-
-
- Selected Tenant:
- {tenantDomain}
-
-
- Selected Backup:
- {props.values.backup.value}
-
-
-
-
-
-
-
-
-
- Overwrite existing configuration
-
-
-
- Send results to Webhook
-
-
-
- Send results to E-Mail
-
-
-
- Send results to PSA
-
-
-
-
-
- >
- )}
-
- )}
-
-
-
-
- )
-}
-
-export default OffboardingWizard
diff --git a/src/views/tenant/standards/BestPracticeAnalyser.jsx b/src/views/tenant/standards/BestPracticeAnalyser.jsx
deleted file mode 100644
index a0e1cb00b101..000000000000
--- a/src/views/tenant/standards/BestPracticeAnalyser.jsx
+++ /dev/null
@@ -1,471 +0,0 @@
-import React, { useEffect, useState } from 'react'
-import {
- CBadge,
- CButton,
- CCard,
- CCardBody,
- CCardHeader,
- CCardText,
- CCardTitle,
- CCol,
- CCollapse,
- CForm,
- CRow,
- CSpinner,
-} from '@coreui/react'
-import useQuery from 'src/hooks/useQuery'
-import PropTypes from 'prop-types'
-import { Field, Form, FormSpy } from 'react-final-form'
-import { RFFCFormInput, RFFCFormSelect } from 'src/components/forms'
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import {
- faChevronRight,
- faChevronDown,
- faSearch,
- faExclamationTriangle,
- faCheck,
- faCross,
- faTimes,
- faSync,
- faExclamation,
-} from '@fortawesome/free-solid-svg-icons'
-import { CippTable, cellBooleanFormatter } from 'src/components/tables'
-import { useSelector } from 'react-redux'
-import { useNavigate } from 'react-router-dom'
-import { CippPage } from 'src/components/layout/CippPage'
-import { useGenericGetRequestQuery, useLazyGenericGetRequestQuery } from 'src/store/api/app'
-import { OnChange } from 'react-final-form-listeners'
-import { queryString } from 'src/helpers'
-import { CellTip, cellGenericFormatter } from 'src/components/tables/CellGenericFormat'
-import { useExecBestPracticeAnalyserMutation } from 'src/store/api/reports'
-import { ModalService } from 'src/components/utilities'
-import { cellTableFormatter } from 'src/components/tables/CellTable'
-import { cellMathFormatter } from 'src/components/tables/CellMathFormatter'
-
-const RefreshAction = ({ singleTenant = false, refreshFunction = null }) => {
- const tenantDomain = useSelector((state) => state.app.currentTenant.defaultDomainName)
- const [execBestPracticeAnalyser, { isLoading, isSuccess, error }] =
- useLazyGenericGetRequestQuery()
- var params = {}
- if (singleTenant) {
- params['TenantFilter'] = tenantDomain
- }
- const showModal = () =>
- ModalService.confirm({
- body: (
-
- Are you sure you want to force the Best Practice Analysis to run? This will slow down
- normal usage considerably.
- Please note: this runs at 3:00 AM UTC automatically every day.
-
- ),
- onConfirm: () =>
- execBestPracticeAnalyser({
- path: 'api/BestPracticeAnalyser_OrchestrationStarter',
- params: params,
- }),
- })
-
- return (
- <>
-
- {isLoading && }
- {error && }
- {isSuccess && }
- {(singleTenant && 'Refresh Tenant Data') || 'Force Refresh All Data'}
-
- {refreshFunction !== null && (
- {
- refreshFunction((Math.random() + 1).toString(36).substring(7))
- }}
- className="m-1"
- size="sm"
- >
-
-
- )}
- >
- )
-}
-RefreshAction.propTypes = {
- singleTenant: PropTypes.bool,
- refreshFunction: PropTypes.func,
-}
-
-const getsubcolumns = (data) => {
- const flatObj = data && data.length > 0 ? data : [{ data: 'No Data Found' }]
- const QueryColumns = []
-
- if (flatObj[0]) {
- Object.keys(flatObj[0]).map((key) => {
- QueryColumns.push({
- name: key,
- selector: (row) => row[key], // Accessing the property using the key
- sortable: true,
- exportSelector: key,
- cell: cellGenericFormatter(),
- })
- })
- }
- return QueryColumns
-}
-const getNestedValue = (obj, path) => {
- if (!path) return undefined
- return path.split('.').reduce((acc, part) => {
- // Check for an array marker
- const match = part.match(/(.*?)\[(\d+)\]/)
- if (match) {
- const propName = match[1]
- const index = parseInt(match[2], 10)
- return acc[propName] ? acc[propName][index] : undefined
- }
- // If no array marker, simply return the property value
- return acc ? acc[part] : undefined
- }, obj)
-}
-const BestPracticeAnalyser = () => {
- const [reportTemplate, setReportTemplate] = useState('CIPP Best Practices v1.0 - Table view')
- const [refreshValue, setRefreshValue] = useState('')
- const { data: templates = [], isLoading: templatesfetch } = useGenericGetRequestQuery({
- path: 'api/listBPATemplates',
- })
- let navigate = useNavigate()
- const tenant = useSelector((state) => state.app.currentTenant)
- let query = useQuery()
- const Report = query.get('Report')
- const SearchNow = query.get('SearchNow')
- const [visibleA, setVisibleA] = useState(true)
- const handleSubmit = async (values) => {
- setVisibleA(false)
- setReportTemplate(values.reportTemplate)
- const shippedValues = {
- SearchNow: true,
- Report: reportTemplate,
- tenantFilter: tenant.customerId,
- random: (Math.random() + 1).toString(36).substring(7),
- }
- var queryString = Object.keys(shippedValues)
- .map((key) => key + '=' + shippedValues[key])
- .join('&')
-
- navigate(`?${queryString}`)
- }
- const [execGraphRequest, graphrequest] = useLazyGenericGetRequestQuery()
- const QueryColumns = {
- set: false,
- data: [
- {
- name: 'Tenant',
- selector: (row) => row['Tenant'],
- sortable: true,
- exportSelector: 'Tenant',
- cell: (row) => CellTip(row['Tenant']),
- },
- ],
- }
- const normalizeTableData = (value) => {
- if (Array.isArray(value)) {
- return value
- } else if (value === null) {
- return null
- } else if (typeof value === 'object') {
- return [value]
- } else {
- return value
- }
- }
- if (graphrequest.isSuccess) {
- if (graphrequest.data.length === 0) {
- graphrequest.data = [{ data: 'No Data Found' }]
- }
- const flatObj = graphrequest.data.Columns.length >= 0 ? graphrequest.data.Columns : []
-
- flatObj.map((col) => {
- if (col === null) {
- return
- }
- // Determine the cell selector based on the 'formatter' property
- let cellSelector
- if (col.formatter) {
- switch (col.formatter) {
- case 'bool':
- cellSelector = cellBooleanFormatter()
- break
- case 'reverseBool':
- cellSelector = cellBooleanFormatter({ reverse: true })
- break
- case 'warnBool':
- cellSelector = cellBooleanFormatter({ warning: true })
- break
- case 'table':
- cellSelector = cellTableFormatter(col.value)
- break
- case 'math':
- cellSelector = cellMathFormatter({ col })
- break
- default:
- cellSelector = cellGenericFormatter()
- break
- }
- } else {
- cellSelector = cellGenericFormatter()
- }
-
- QueryColumns.data.push({
- name: col.name,
- selector: (row) => getNestedValue(row, col.value),
- sortable: true,
- exportSelector: col.value.split('.').join('/'),
- cell: cellSelector, // Use the determined cell selector
- })
- })
-
- QueryColumns.set = true
- }
-
- useEffect(() => {
- execGraphRequest({
- path: 'api/listBPA',
- params: {
- tenantFilter: tenant.customerId,
- Report: reportTemplate,
- SearchNow: SearchNow,
- refresh: refreshValue,
- },
- })
- }, [
- Report,
- execGraphRequest,
- tenant.defaultDomainName,
- query,
- refreshValue,
- reportTemplate,
- tenant.customerId,
- SearchNow,
- ])
- return (
- <>
-
-
-
-
-
- Report Settings
- setVisibleA(!visibleA)}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {graphrequest.isUninitialized && Choose a BPA Report to get started. }
- {graphrequest.isFetching && }
- {graphrequest.isSuccess && QueryColumns.set && graphrequest.data.Style == 'Table' && (
-
-
- Best Practice Report
-
-
- ,
- ],
- }}
- />
-
-
- )}
- {graphrequest.isSuccess && QueryColumns.set && graphrequest.data.Style == 'Tenant' && (
- <>
-
-
-
-
- {graphrequest.data?.Data[0] &&
- Object.keys(graphrequest.data.Data[0]).length === 0 ? (
-
-
- Best Practice Report
-
-
-
- No Data Found for this tenant. Please refresh the tenant data.
-
-
-
- ) : (
- graphrequest.data.Columns.map((info, idx) => (
-
-
-
- {info.name}
-
-
-
- {info.formatter === 'bool' && (
-
-
- {graphrequest.data.Data[0][info.value] ? 'Yes' : 'No'}
-
- )}
- {info.formatter === 'reverseBool' && (
-
-
- {graphrequest.data.Data[0][info.value] ? 'No' : 'Yes'}
-
- )}
- {info.formatter === 'warnBool' && (
-
-
- {graphrequest.data.Data[0][info.value] ? 'Yes' : 'No'}
-
- )}
-
- {info.formatter === 'table' && (
- <>
-
- >
- )}
-
- {info.formatter === 'number' && (
-
- {getNestedValue(graphrequest.data.Data[0], info.value)}
-
- )}
-
-
- {info.desc}
-
-
-
-
- ))
- )}
-
- >
- )}
-
-
-
- >
- )
-}
-
-export default BestPracticeAnalyser
diff --git a/version_latest.txt b/version_latest.txt
index 4c77920fd2c5..5e39348ef037 100644
--- a/version_latest.txt
+++ b/version_latest.txt
@@ -1 +1 @@
-6.4.1
+99.99.99
\ No newline at end of file