diff --git a/package.json b/package.json index f92f847989c0..ed6174da5afa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cipp", - "version": "5.8.5", + "version": "5.9.0", "description": "The CyberDrain Improved Partner Portal is a portal to help manage administration for Microsoft Partners.", "homepage": "https://cipp.app/", "bugs": { diff --git a/public/version_latest.txt b/public/version_latest.txt index a075da200b96..b3d91f9cfc04 100644 --- a/public/version_latest.txt +++ b/public/version_latest.txt @@ -1 +1 @@ -5.8.5 +5.9.0 diff --git a/src/_nav.jsx b/src/_nav.jsx index ada800050fc5..874b6e28eb42 100644 --- a/src/_nav.jsx +++ b/src/_nav.jsx @@ -45,6 +45,11 @@ const _nav = [ name: 'Users', to: '/identity/administration/users', }, + { + component: CNavItem, + name: 'Risky Users', + to: '/identity/administration/risky-users', + }, { component: CNavItem, name: 'Groups', @@ -114,6 +119,11 @@ const _nav = [ name: 'AAD Connect Report', to: '/identity/reports/azure-ad-connect-report', }, + { + component: CNavItem, + name: 'Risk Detections', + to: '/identity/reports/risk-detections', + }, ], }, { diff --git a/src/components/layout/AppHeader.jsx b/src/components/layout/AppHeader.jsx index c62f6008657e..3d3636d0e426 100644 --- a/src/components/layout/AppHeader.jsx +++ b/src/components/layout/AppHeader.jsx @@ -101,13 +101,19 @@ const AppHeader = () => { //check if the value of this key is false. If so, set the setupCompleted state to false //if none is found, set the setupCompleted state to true useEffect(() => { - if (dashboard && dashboard.length >= 1) { - const setupCompleted = dashboard.find((alert) => alert.setupCompleted === false) + if (dashboard && Array.isArray(dashboard) && dashboard.length >= 1) { + console.log('Finding if setup is completed.') + const setupCompleted = dashboard.find((alert) => alert && alert.setupCompleted === false) if (setupCompleted) { + console.log("Setup isn't completed yet, we found a match with false.") dispatch(setSetupCompleted({ setupCompleted: false })) } else { + console.log('Setup is completed.') dispatch(setSetupCompleted({ setupCompleted: true })) } + } else { + console.log('Setup is completed.') + dispatch(setSetupCompleted({ setupCompleted: true })) } }, [dashboard, dispatch]) diff --git a/src/components/tables/CippTable.jsx b/src/components/tables/CippTable.jsx index c0f6ff6d8b19..8db2dbcf1db4 100644 --- a/src/components/tables/CippTable.jsx +++ b/src/components/tables/CippTable.jsx @@ -645,9 +645,13 @@ export default function CippTable({ Object.assign(output, flatten(value, newKey)) } else { if (Array.isArray(value)) { - value.map((item, idx) => { - Object.assign(output, flatten(item, `${newKey}[${idx}]`)) - }) + if (typeof value[0] === 'object') { + value.map((item, idx) => { + Object.assign(output, flatten(item, `${newKey}[${idx}]`)) + }) + } else { + output[newKey] = value + } } else { output[newKey] = value } @@ -683,8 +687,7 @@ export default function CippTable({ }) return Array.isArray(exportData) && exportData.length > 0 ? exportData.map((obj) => { - const flattenedObj = flatten(obj) - return applyFormatter(flattenedObj) + return flatten(applyFormatter(obj)) }) : [] } @@ -695,8 +698,7 @@ export default function CippTable({ // Adjusted dataFlat processing to include formatting let dataFlat = Array.isArray(data) ? data.map((item) => { - const flattenedItem = flatten(item) - return applyFormatter(flattenedItem) + return flatten(applyFormatter(item)) }) : [] if (!disablePDFExport) { diff --git a/src/importsMap.jsx b/src/importsMap.jsx index b50612327848..6cd0031a1c6c 100644 --- a/src/importsMap.jsx +++ b/src/importsMap.jsx @@ -15,6 +15,7 @@ import React from 'react' "/identity/administration/jit-admin": React.lazy(() => import('./views/identity/administration/DeployJITAdmin')), "/identity/administration/ViewBec": React.lazy(() => import('./views/identity/administration/ViewBEC')), "/identity/administration/users": React.lazy(() => import('./views/identity/administration/Users')), + "/identity/administration/risky-users": React.lazy(() => import('./views/identity/administration/RiskyUsers')), "/identity/administration/devices": React.lazy(() => import('./views/identity/administration/Devices')), "/identity/administration/groups/add": React.lazy(() => import('./views/identity/administration/AddGroup')), "/identity/administration/group-templates": React.lazy(() => import('./views/identity/administration/GroupTemplates')), @@ -32,6 +33,7 @@ import React from 'react' "/identity/reports/inactive-users-report": React.lazy(() => import('./views/identity/reports/InactiveUsers')), "/identity/reports/Signin-report": React.lazy(() => import('./views/identity/reports/SignIns')), "/identity/reports/azure-ad-connect-report": React.lazy(() => import('./views/identity/reports/AzureADConnectReport')), + "/identity/reports/risk-detections": React.lazy(() => import('./views/identity/reports/RiskDetections')), "/tenant/administration/tenants": React.lazy(() => import('./views/tenant/administration/Tenants')), "/tenant/administration/tenants/edit": React.lazy(() => import('./views/tenant/administration/EditTenant')), "/tenant/administration/partner-relationships": React.lazy(() => import('./views/tenant/administration/PartnerRelationships')), diff --git a/src/routes.json b/src/routes.json index f27aaa5b148e..2975b4c168ac 100644 --- a/src/routes.json +++ b/src/routes.json @@ -99,6 +99,12 @@ "component": "views/identity/administration/Users", "allowedRoles": ["admin", "editor", "readonly"] }, + { + "path": "/identity/administration/risky-users", + "name": "Risky Users", + "component": "views/identity/administration/RiskyUsers", + "allowedRoles": ["admin", "editor", "readonly"] + }, { "path": "/identity/administration/devices", "name": "Devices", @@ -206,6 +212,12 @@ "component": "views/identity/reports/AzureADConnectReport", "allowedRoles": ["admin", "editor", "readonly"] }, + { + "path": "/identity/reports/risk-detections", + "name": "Risk Detections", + "component": "views/identity/reports/RiskDetections", + "allowedRoles": ["admin", "editor", "readonly"] + }, { "path": "/tenant", "name": "Tenant", diff --git a/src/views/identity/administration/RiskyUsers.jsx b/src/views/identity/administration/RiskyUsers.jsx new file mode 100644 index 000000000000..d1ffc4ad0499 --- /dev/null +++ b/src/views/identity/administration/RiskyUsers.jsx @@ -0,0 +1,103 @@ +import { useSelector } from 'react-redux' +import { CippPageList } from 'src/components/layout' + +const columns = [ + { + name: 'Risk Last Updated Date', + selector: (row) => row['riskLastUpdatedDateTime'], + sortable: true, + exportSelector: 'riskLastUpdatedDateTime', + }, + { + name: 'User Principal Name', + selector: (row) => row['userPrincipalName'], + sortable: true, + exportSelector: 'userPrincipalName', + }, + { + name: 'Risk Level', + selector: (row) => row['riskLevel'], + sortable: true, + exportSelector: 'riskLevel', + }, + { + name: 'Risk State', + selector: (row) => row['riskState'], + sortable: true, + exportSelector: 'riskState', + }, + { + name: 'Risk Detail', + selector: (row) => row['riskDetail'], + sortable: true, + exportSelector: 'riskDetail', + }, + { + name: 'isProcessing', + selector: (row) => row['isProcessing'], + sortable: true, + exportSelector: 'isProcessing', + }, + { + name: 'isDeleted', + selector: (row) => row['isDeleted'], + sortable: true, + exportSelector: 'isDeleted', + }, +] + +const RiskyUsers = () => { + const tenant = useSelector((state) => state.app.currentTenant) + + return ( + <> + + + ) +} + +export default RiskyUsers diff --git a/src/views/identity/reports/RiskDetections.jsx b/src/views/identity/reports/RiskDetections.jsx new file mode 100644 index 000000000000..ed1604acda6e --- /dev/null +++ b/src/views/identity/reports/RiskDetections.jsx @@ -0,0 +1,125 @@ +import { useSelector } from 'react-redux' +import { CippPageList } from 'src/components/layout' +import { CellTip } from 'src/components/tables' + +const columns = [ + { + name: 'Detected Date', + selector: (row) => row['detectedDateTime'], + sortable: true, + exportSelector: 'detectedDateTime', + }, + { + name: 'User Principal Name', + selector: (row) => row['userPrincipalName'], + sortable: true, + exportSelector: 'userPrincipalName', + }, + { + name: 'Location', + selector: (row) => `${row.location?.city} - ${row.location?.countryOrRegion}`, + sortable: true, + exportSelector: 'Location', + cell: (row) => CellTip(`${row.location?.city} - ${row.location?.countryOrRegion}`), + }, + { + name: 'IP Address', + selector: (row) => row['ipAddress'], + sortable: true, + exportSelector: 'ipAddress', + }, + { + name: 'Risk State', + selector: (row) => row['riskState'], + sortable: true, + exportSelector: 'riskState', + }, + { + name: 'Risk Detail', + selector: (row) => row['riskDetail'], + sortable: true, + exportSelector: 'riskDetail', + }, + { + name: 'Risk Level', + selector: (row) => row['riskLevel'], + sortable: true, + exportSelector: 'riskLevel', + }, + { + name: 'Risk Type', + selector: (row) => row['riskType'], + sortable: true, + exportSelector: 'riskType', + }, + { + name: 'Risk Event Type', + selector: (row) => row['riskEventType'], + sortable: true, + exportSelector: 'riskEventType', + }, + { + name: 'Detection Type', + selector: (row) => row['detectionTimingType'], + sortable: true, + exportSelector: 'detectionTimingType', + }, + { + name: 'Activity', + selector: (row) => row['activity'], + sortable: true, + exportSelector: 'activity', + }, +] + +const RiskDetections = () => { + const tenant = useSelector((state) => state.app.currentTenant) + + return ( + <> + + + ) +} + +export default RiskDetections diff --git a/src/views/identity/reports/SignIns.jsx b/src/views/identity/reports/SignIns.jsx index 0e78095db5d1..45934e5de02b 100644 --- a/src/views/identity/reports/SignIns.jsx +++ b/src/views/identity/reports/SignIns.jsx @@ -201,6 +201,12 @@ const SignInsReport = () => { title="Sign Ins Report" capabilities={{ allTenants: false, helpContext: 'https://google.com' }} datatable={{ + filterlist: [ + { + filterName: 'Risky sign-ins', + filter: 'Complex: riskState ne none', + }, + ], columns: columns, path: `/api/ListSignIns`, reportName: `${tenant?.defaultDomainName}-SignIns-Report`, diff --git a/version_latest.txt b/version_latest.txt index a075da200b96..b3d91f9cfc04 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -5.8.5 +5.9.0