Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev to hotfix #2174

Merged
merged 10 commits into from
Feb 26, 2024
2 changes: 1 addition & 1 deletion public/version_latest.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.2.0
5.2.1
43 changes: 41 additions & 2 deletions src/components/forms/RFFComponents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
CTooltip,
} from '@coreui/react'
import Select from 'react-select'
import Creatable, { useCreatable } from 'react-select/creatable'
import { Field } from 'react-final-form'
import { FieldArray } from 'react-final-form-arrays'
import React, { useState, useMemo, useRef } from 'react'
Expand Down Expand Up @@ -393,6 +394,7 @@ export const RFFSelectSearch = ({
disabled = false,
retainInput = true,
isLoading = false,
allowCreate = false,
refreshFunction,
props,
}) => {
Expand Down Expand Up @@ -433,7 +435,7 @@ export const RFFSelectSearch = ({
</CTooltip>
)}
</CFormLabel>
{onChange && (
{!allowCreate && onChange && (
<Select
className="react-select-container"
classNamePrefix="react-select"
Expand All @@ -452,7 +454,7 @@ export const RFFSelectSearch = ({
{...props}
/>
)}
{!onChange && (
{!allowCreate && !onChange && (
<Select
className="react-select-container"
classNamePrefix="react-select"
Expand All @@ -470,6 +472,43 @@ export const RFFSelectSearch = ({
{...props}
/>
)}
{allowCreate && onChange && (
<Creatable
className="react-select-container"
classNamePrefix="react-select"
{...input}
isClearable={false}
name={name}
id={name}
disabled={disabled}
options={selectSearchvalues}
placeholder={placeholder}
isMulti={multi}
onChange={onChange}
onInputChange={debounceOnInputChange}
inputValue={inputText}
isLoading={isLoading}
{...props}
/>
)}
{allowCreate && !onChange && (
<Creatable
className="react-select-container"
classNamePrefix="react-select"
{...input}
isClearable={true}
name={name}
id={name}
disabled={disabled}
options={selectSearchvalues}
placeholder={placeholder}
onInputChange={setOnInputChange}
isMulti={multi}
inputValue={inputText}
isLoading={isLoading}
{...props}
/>
)}
{meta.error && meta.touched && <span className="text-danger">{meta.error}</span>}
</div>
)
Expand Down
30 changes: 20 additions & 10 deletions src/views/identity/reports/MFAReport.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,20 @@ const columns = [
cell: cellBooleanFormatter({ colourless: true }),
exportSelector: 'isLicensed',
},
{
selector: (row) => row['PerUser'],
name: 'Per user MFA Status',
sortable: true,
exportSelector: 'PerUser',
},
{
selector: (row) => row['MFARegistration'],
name: 'Registered for Conditional MFA',
sortable: true,
cell: cellBooleanFormatter(),
exportSelector: 'MFARegistration',
},
{
selector: (row) => row['CoveredBySD'],
name: 'Enforced via Security Defaults',
sortable: true,
cell: cellBooleanFormatter({ colourless: true }),
exportSelector: 'CoveredBySD',
},
{
selector: (row) => row['CoveredByCA'],
name: 'Enforced via Conditional Access',
Expand All @@ -46,11 +47,10 @@ const columns = [
exportSelector: 'CoveredByCA',
},
{
selector: (row) => row['CoveredBySD'],
name: 'Enforced via Security Defaults',
selector: (row) => row['PerUser'],
name: 'Per user MFA Status',
sortable: true,
cell: cellBooleanFormatter({ colourless: true }),
exportSelector: 'CoveredBySD',
exportSelector: 'PerUser',
},
]

Expand Down Expand Up @@ -134,7 +134,17 @@ const MFAList = () => {
datatable={{
filterlist: [
{ filterName: 'Enabled users', filter: '"accountEnabled":true' },
{ filterName: 'Non-guest users', filter: 'Complex: UPN notlike #EXT#' },
{ filterName: 'Licensed users', filter: 'Complex: IsLicensed eq true' },
{
filterName: 'Enabled, licensed non-guest users missing MFA',
filter:
'Complex: UPN notlike #EXT#; IsLicensed eq true; accountEnabled eq true; MFARegistration eq false',
},
{
filterName: 'No MFA methods registered',
filter: 'Complex: MFARegistration eq false',
},
],
columns: tenant.defaultDomainName === 'AllTenants' ? Altcolumns : columns,
path: '/api/ListMFAUsers',
Expand Down
93 changes: 83 additions & 10 deletions src/views/tenant/administration/GraphExplorer.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState, useRef } from 'react'
import React, { useEffect, useState, useRef, useMemo } from 'react'
import {
CAlert,
CButton,
Expand Down Expand Up @@ -31,6 +31,7 @@ import { OnChange } from 'react-final-form-listeners'
import { cellGenericFormatter } from 'src/components/tables/CellGenericFormat'
import PropTypes from 'prop-types'
import { CippCodeOffCanvas, ModalService } from 'src/components/utilities'
import { debounce } from 'lodash-es'

const GraphExplorer = () => {
const tenant = useSelector((state) => state.app.currentTenant)
Expand All @@ -39,6 +40,7 @@ const GraphExplorer = () => {
const [alertVisible, setAlertVisible] = useState()
const [random, setRandom] = useState('')
const [random2, setRandom2] = useState('')
const [random3, setRandom3] = useState('')
const [ocVisible, setOCVisible] = useState(false)
const [searchNow, setSearchNow] = useState(false)
const [visibleA, setVisibleA] = useState(true)
Expand All @@ -49,13 +51,30 @@ const GraphExplorer = () => {
}
const [execGraphRequest, graphrequest] = useLazyGenericGetRequestQuery()
const [execPostRequest, postResults] = useLazyGenericPostRequestQuery()
const [execPropRequest, availableProperties] = useLazyGenericGetRequestQuery()
const {
data: customPresets = [],
isFetching: presetsIsFetching,
error: presetsError,
} = useGenericGetRequestQuery({ path: '/api/ListGraphExplorerPresets', params: { random2 } })
const QueryColumns = { set: false, data: [] }

function endpointChange(value) {
execPropRequest({
path: '/api/ListGraphRequest',
params: {
Endpoint: value,
ListProperties: true,
TenantFilter: tenant.defaultDomainName,
IgnoreErrors: true,
random: (Math.random() + 1).toString(36).substring(7),
},
})
}
const debounceEndpointChange = useMemo(() => {
return debounce(endpointChange, 1000)
}, [endpointChange])

if (graphrequest.isSuccess) {
if (graphrequest.data?.Results?.length > 0) {
//set columns
Expand Down Expand Up @@ -217,10 +236,15 @@ const GraphExplorer = () => {

useEffect(() => {
if (params?.endpoint) {
var select = ''
if (params?.$select) {
select = params.$select.map((p) => p.value).join(',')
}
execGraphRequest({
path: 'api/ListGraphRequest',
params: {
...params,
$select: select,
random: random,
},
})
Expand All @@ -237,15 +261,36 @@ const GraphExplorer = () => {
{({ form }) => (
<OnChange name={field}>
{(value) => {
if (field == 'endpoint') {
debounceEndpointChange(value)
}
if (value?.value) {
let preset = presets.filter(function (obj) {
return obj.id === value.value
})
if (preset[0]?.id !== '') {
if (preset[0]?.params[set]) {
onChange(preset[0]?.params[set])
if (set == 'endpoint') {
debounceEndpointChange(preset[0]?.params[set])
}
if (set == '$select') {
if (preset[0]?.params[set]) {
var properties = preset[0].params[set].split(',')
var selectedProps = properties.map((prop) => {
return {
label: prop,
value: prop,
}
})
onChange(selectedProps)
} else {
onChange('')
}
} else {
onChange(preset[0][set])
if (preset[0]?.params[set]) {
onChange(preset[0]?.params[set])
} else {
onChange(preset[0][set])
}
}
}
}
Expand All @@ -263,6 +308,10 @@ const GraphExplorer = () => {

function getPresetProps(values) {
var newvals = Object.assign({}, values)
console.log(newvals)
if (newvals?.$select !== undefined && Array.isArray(newvals?.$select)) {
newvals.$select = newvals?.$select.map((p) => p.value).join(',')
}
delete newvals['reportTemplate']
delete newvals['tenantFilter']
delete newvals['IsShared']
Expand Down Expand Up @@ -454,19 +503,38 @@ const GraphExplorer = () => {
placeholder="Enter the Graph Endpoint you'd like to run the custom report for."
/>
<WhenFieldChanges field="reportTemplate" set="endpoint" />
<WhenFieldChanges field="endpoint" set="endpoint" />
<RFFCFormInput
type="text"
name="$filter"
label="Filter"
placeholder="Enter the filter string for the Graph query"
/>
<WhenFieldChanges field="reportTemplate" set="$filter" />
<RFFCFormInput
type="text"
name="$select"
label="Select"
placeholder="Select the columns to use for this query"
/>
<div className="mb-3">
<RFFSelectSearch
name="$select"
label="Select"
placeholder="Select the columns to use for this query"
retainInput={true}
multi={true}
values={
availableProperties?.data?.Results
? availableProperties?.data?.Results.map((prop) => {
return {
name: prop,
value: prop,
}
})
: []
}
allowCreate={true}
refreshFunction={() =>
setRandom3((Math.random() + 1).toString(36).substring(7))
}
isLoading={availableProperties.isFetching}
/>
</div>
<WhenFieldChanges field="reportTemplate" set="$select" />
<RFFCFormInput
type="text"
Expand Down Expand Up @@ -504,6 +572,11 @@ const GraphExplorer = () => {
<hr />
<CippPage title="Report Results" tenantSelector={false}>
{!searchNow && <span>Execute a search to get started.</span>}
{graphrequest.isFetching && (
<div className="my-2">
<CSpinner className="me-2" /> Loading Data
</div>
)}
{graphrequest.isSuccess && QueryColumns.set && searchNow && (
<CCard className="content-card">
<CCardHeader className="d-flex justify-content-between align-items-center">
Expand Down
2 changes: 1 addition & 1 deletion version_latest.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.2.0
5.2.1
Loading