diff --git a/src/api/ApiCall.jsx b/src/api/ApiCall.jsx
index e4d9a366908c..a2d7d0396ce1 100644
--- a/src/api/ApiCall.jsx
+++ b/src/api/ApiCall.jsx
@@ -50,7 +50,7 @@ export function ApiGetCall(props) {
title: `${
error.config?.params?.tenantFilter ? error.config?.params?.tenantFilter : ""
} Error`,
- })
+ }),
);
}
return returnRetry;
@@ -211,7 +211,7 @@ export function ApiPostCall({ relatedQueryKeys, onResult }) {
if (!query.queryKey || !query.queryKey[0]) return false;
const queryKeyStr = String(query.queryKey[0]);
const matches = wildcardPatterns.some((pattern) =>
- queryKeyStr.startsWith(pattern)
+ queryKeyStr.startsWith(pattern),
);
// Debug logging for each query check
@@ -220,7 +220,7 @@ export function ApiPostCall({ relatedQueryKeys, onResult }) {
queryKey: query.queryKey,
queryKeyStr,
matchedPattern: wildcardPatterns.find((pattern) =>
- queryKeyStr.startsWith(pattern)
+ queryKeyStr.startsWith(pattern),
),
});
}
@@ -252,8 +252,9 @@ export function ApiGetCallWithPagination({
waiting = true,
}) {
const dispatch = useDispatch();
+ const queryClient = useQueryClient();
const MAX_RETRIES = retry;
- const HTTP_STATUS_TO_NOT_RETRY = [401, 403, 404];
+ const HTTP_STATUS_TO_NOT_RETRY = [302, 401, 403, 404, 500];
const retryFn = (failureCount, error) => {
let returnRetry = true;
@@ -261,6 +262,12 @@ export function ApiGetCallWithPagination({
returnRetry = false;
}
if (isAxiosError(error) && HTTP_STATUS_TO_NOT_RETRY.includes(error.response?.status ?? 0)) {
+ if (
+ error.response?.status === 302 &&
+ error.response?.headers.get("location").includes("/.auth/login/aad")
+ ) {
+ queryClient.invalidateQueries({ queryKey: ["authmecipp"] });
+ }
returnRetry = false;
}
@@ -270,7 +277,7 @@ export function ApiGetCallWithPagination({
message: getCippError(error),
title: "Error",
toastError: error,
- })
+ }),
);
}
return returnRetry;
diff --git a/src/layouts/config.js b/src/layouts/config.js
index 8e8fd1f97c39..82e68a157e9c 100644
--- a/src/layouts/config.js
+++ b/src/layouts/config.js
@@ -721,6 +721,11 @@ export const nativeMenuItems = [
path: "/email/reports/mailbox-permissions",
permissions: ["Exchange.Mailbox.*"],
},
+ {
+ title: "Calendar Permissions",
+ path: "/email/reports/calendar-permissions",
+ permissions: ["Exchange.Mailbox.*"],
+ },
{
title: "Anti-Phishing Filters",
path: "/email/reports/antiphishing-filters",
diff --git a/src/pages/cipp/logs/index.js b/src/pages/cipp/logs/index.js
index 18f8ad68174c..41eac2225d46 100644
--- a/src/pages/cipp/logs/index.js
+++ b/src/pages/cipp/logs/index.js
@@ -37,7 +37,7 @@ const pageTitle = "Logbook Results";
const actions = [
{
label: "View Log Entry",
- link: "/cipp/logs/logentry?logentry=[RowKey]",
+ link: "/cipp/logs/logentry?logentry=[RowKey]&dateFilter=[DateFilter]",
icon: ,
color: "primary",
},
@@ -100,14 +100,14 @@ const Page = () => {
setStartDate(
data.startDate
? new Date(data.startDate * 1000).toISOString().split("T")[0].replace(/-/g, "")
- : null
+ : null,
);
// Format end date if available
setEndDate(
data.endDate
? new Date(data.endDate * 1000).toISOString().split("T")[0].replace(/-/g, "")
- : null
+ : null,
);
// Set username filter if available
@@ -117,7 +117,7 @@ const Page = () => {
setSeverity(
data.severity && data.severity.length > 0
? data.severity.map((item) => item.value).join(",")
- : null
+ : null,
);
// Close the accordion after applying filters
@@ -157,13 +157,13 @@ const Page = () => {
<>
{startDate
? new Date(
- startDate.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3") + "T00:00:00"
+ startDate.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3") + "T00:00:00",
).toLocaleDateString()
: new Date().toLocaleDateString()}
{startDate && endDate ? " - " : ""}
{endDate
? new Date(
- endDate.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3") + "T00:00:00"
+ endDate.replace(/(\d{4})(\d{2})(\d{2})/, "$1-$2-$3") + "T00:00:00",
).toLocaleDateString()
: ""}
>
diff --git a/src/pages/cipp/logs/logentry.js b/src/pages/cipp/logs/logentry.js
index 2dbb4a23a5a7..175dcc915aba 100644
--- a/src/pages/cipp/logs/logentry.js
+++ b/src/pages/cipp/logs/logentry.js
@@ -11,12 +11,13 @@ import { getCippTranslation } from "../../../utils/get-cipp-translation";
const Page = () => {
const router = useRouter();
- const { logentry } = router.query;
+ const { logentry, dateFilter } = router.query;
const logRequest = ApiGetCall({
url: `/api/Listlogs`,
data: {
logentryid: logentry,
+ dateFilter: dateFilter,
},
queryKey: `GetLogEntry-${logentry}`,
waiting: !!logentry,
@@ -44,12 +45,12 @@ const Page = () => {
logData.Severity === "CRITICAL"
? "error"
: logData.Severity === "Error"
- ? "error"
- : logData.Severity === "Warn"
- ? "warning"
- : logData.Severity === "Info"
- ? "info"
- : "default"
+ ? "error"
+ : logData.Severity === "Warn"
+ ? "warning"
+ : logData.Severity === "Info"
+ ? "info"
+ : "default"
}
variant="filled"
/>
diff --git a/src/pages/email/reports/calendar-permissions/index.js b/src/pages/email/reports/calendar-permissions/index.js
new file mode 100644
index 000000000000..d945e29b8c10
--- /dev/null
+++ b/src/pages/email/reports/calendar-permissions/index.js
@@ -0,0 +1,117 @@
+import { Layout as DashboardLayout } from "/src/layouts/index.js";
+import { CippTablePage } from "/src/components/CippComponents/CippTablePage.jsx";
+import { useState } from "react";
+import {
+ Button,
+ FormControlLabel,
+ Switch,
+ Alert,
+ SvgIcon,
+ IconButton,
+ Tooltip,
+} from "@mui/material";
+import { useSettings } from "../../../../hooks/use-settings";
+import { Stack } from "@mui/system";
+import { Sync, Info } from "@mui/icons-material";
+import { useDialog } from "../../../../hooks/use-dialog";
+import { CippApiDialog } from "../../../../components/CippComponents/CippApiDialog";
+
+const Page = () => {
+ const [byUser, setByUser] = useState(true);
+ const currentTenant = useSettings().currentTenant;
+ const syncDialog = useDialog();
+
+ const isAllTenants = currentTenant === "AllTenants";
+
+ const columns = byUser
+ ? [
+ ...(isAllTenants ? ["Tenant"] : []),
+ "User",
+ "UserMailboxType",
+ "Permissions",
+ "MailboxCacheTimestamp",
+ "PermissionCacheTimestamp",
+ ]
+ : [
+ ...(isAllTenants ? ["Tenant"] : []),
+ "CalendarUPN",
+ "CalendarDisplayName",
+ "CalendarType",
+ "Permissions",
+ "MailboxCacheTimestamp",
+ "PermissionCacheTimestamp",
+ ];
+
+ // Compute apiData based on byUser directly (no useState needed)
+ const apiData = {
+ UseReportDB: true,
+ ByUser: byUser,
+ };
+
+ const pageActions = [
+
+
+
+
+
+
+
+ setByUser(e.target.checked)} color="primary" />
+ }
+ label="Group by User"
+ labelPlacement="start"
+ />
+ ,
+ ];
+
+ return (
+ <>
+ {currentTenant && currentTenant !== "" ? (
+
+ ) : (
+ Please select a tenant to view calendar permissions.
+ )}
+
+ >
+ );
+};
+
+Page.getLayout = (page) => {page};
+
+export default Page;
diff --git a/src/pages/tenant/manage/applied-standards.js b/src/pages/tenant/manage/applied-standards.js
index 5b6539767fce..ef11f5e33e34 100644
--- a/src/pages/tenant/manage/applied-standards.js
+++ b/src/pages/tenant/manage/applied-standards.js
@@ -35,6 +35,7 @@ import {
NotificationImportant,
Construction,
Schedule,
+ Check,
} from "@mui/icons-material";
import standards from "/src/data/standards.json";
import { CippApiDialog } from "../../../components/CippComponents/CippApiDialog";
@@ -91,7 +92,7 @@ const Page = () => {
// Selected template object (safe lookup)
const selectedTemplate = useMemo(
() => templates.find((t) => t.GUID === templateId),
- [templates, templateId]
+ [templates, templateId],
);
// Run the report once
@@ -123,7 +124,7 @@ const Page = () => {
useEffect(() => {
if (templateId && templateDetails.isSuccess && templateDetails.data) {
const selectedTemplate = templateDetails.data.find(
- (template) => template.GUID === templateId
+ (template) => template.GUID === templateId,
);
if (selectedTemplate && comparisonApi.isSuccess && comparisonApi.data) {
@@ -157,30 +158,55 @@ const Page = () => {
const itemTemplateId = expandedTemplate.GUID;
const standardId = `standards.IntuneTemplate.${itemTemplateId}`;
const standardInfo = standards.find(
- (s) => s.name === `standards.IntuneTemplate`
+ (s) => s.name === `standards.IntuneTemplate`,
);
// Find the tenant's value for this specific template
const currentTenantStandard = currentTenantData.find(
- (s) => s.standardId === standardId
+ (s) => s.standardId === standardId,
);
// Get the standard object and its value from the tenant object
const standardObject = currentTenantObj?.[standardId];
const directStandardValue = standardObject?.Value;
- // Determine compliance status
+ // Determine compliance status - match main logic
let isCompliant = false;
- // For IntuneTemplate, the value is true if compliant, or an object with comparison data if not compliant
- if (directStandardValue === true) {
- isCompliant = true;
- } else if (
- directStandardValue !== undefined &&
- typeof directStandardValue !== "object"
+ // FIRST: Check if CurrentValue and ExpectedValue exist and match
+ if (
+ standardObject?.CurrentValue !== undefined &&
+ standardObject?.ExpectedValue !== undefined
) {
+ const sortedCurrent =
+ typeof standardObject.CurrentValue === "object" &&
+ standardObject.CurrentValue !== null
+ ? Object.keys(standardObject.CurrentValue)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = standardObject.CurrentValue[key];
+ return obj;
+ }, {})
+ : standardObject.CurrentValue;
+ const sortedExpected =
+ typeof standardObject.ExpectedValue === "object" &&
+ standardObject.ExpectedValue !== null
+ ? Object.keys(standardObject.ExpectedValue)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = standardObject.ExpectedValue[key];
+ return obj;
+ }, {})
+ : standardObject.ExpectedValue;
+ isCompliant =
+ JSON.stringify(sortedCurrent) === JSON.stringify(sortedExpected);
+ }
+ // SECOND: Check if Value is explicitly true
+ else if (directStandardValue === true) {
isCompliant = true;
- } else if (currentTenantStandard) {
+ }
+ // THIRD: Fall back to currentTenantStandard
+ else if (currentTenantStandard) {
isCompliant = currentTenantStandard.value === true;
}
@@ -220,8 +246,8 @@ const Page = () => {
complianceStatus: isOverridden
? "Overridden"
: isCompliant
- ? "Compliant"
- : "Non-Compliant",
+ ? "Compliant"
+ : "Non-Compliant",
isOverridden,
overridingTemplateId: isOverridden ? tenantTemplateId : null,
overridingTemplateName,
@@ -258,12 +284,12 @@ const Page = () => {
if (itemTemplateId) {
const standardId = `standards.IntuneTemplate.${itemTemplateId}`;
const standardInfo = standards.find(
- (s) => s.name === `standards.IntuneTemplate`
+ (s) => s.name === `standards.IntuneTemplate`,
);
// Find the tenant's value for this specific template
const currentTenantStandard = currentTenantData.find(
- (s) => s.standardId === standardId
+ (s) => s.standardId === standardId,
);
// Get the standard object and its value from the tenant object
@@ -320,8 +346,8 @@ const Page = () => {
complianceStatus: isOverridden
? "Overridden"
: isCompliant
- ? "Compliant"
- : "Non-Compliant",
+ ? "Compliant"
+ : "Non-Compliant",
isOverridden,
overridingTemplateId: isOverridden ? tenantTemplateId : null,
overridingTemplateName,
@@ -374,12 +400,12 @@ const Page = () => {
const itemTemplateId = expandedTemplate.GUID;
const standardId = `standards.ConditionalAccessTemplate.${itemTemplateId}`;
const standardInfo = standards.find(
- (s) => s.name === `standards.ConditionalAccessTemplate`
+ (s) => s.name === `standards.ConditionalAccessTemplate`,
);
// Find the tenant's value for this specific template
const currentTenantStandard = currentTenantData.find(
- (s) => s.standardId === standardId
+ (s) => s.standardId === standardId,
);
const standardObject = currentTenantObj?.[standardId];
const directStandardValue = standardObject?.Value;
@@ -390,10 +416,40 @@ const Page = () => {
: null;
let isCompliant = false;
- // For ConditionalAccessTemplate, the value is true if compliant, or an object with comparison data if not compliant
- if (directStandardValue === true) {
+ // FIRST: Check if CurrentValue and ExpectedValue exist and match
+ if (
+ standardObject?.CurrentValue !== undefined &&
+ standardObject?.ExpectedValue !== undefined
+ ) {
+ const sortedCurrent =
+ typeof standardObject.CurrentValue === "object" &&
+ standardObject.CurrentValue !== null
+ ? Object.keys(standardObject.CurrentValue)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = standardObject.CurrentValue[key];
+ return obj;
+ }, {})
+ : standardObject.CurrentValue;
+ const sortedExpected =
+ typeof standardObject.ExpectedValue === "object" &&
+ standardObject.ExpectedValue !== null
+ ? Object.keys(standardObject.ExpectedValue)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = standardObject.ExpectedValue[key];
+ return obj;
+ }, {})
+ : standardObject.ExpectedValue;
+ isCompliant =
+ JSON.stringify(sortedCurrent) === JSON.stringify(sortedExpected);
+ }
+ // SECOND: Check if Value is explicitly true
+ else if (directStandardValue === true) {
isCompliant = true;
- } else {
+ }
+ // THIRD: Otherwise not compliant
+ else {
isCompliant = false;
}
@@ -423,8 +479,8 @@ const Page = () => {
complianceStatus: isOverridden
? "Overridden"
: isCompliant
- ? "Compliant"
- : "Non-Compliant",
+ ? "Compliant"
+ : "Non-Compliant",
complianceDetails:
standardInfo?.docsDescription || standardInfo?.helpText || "",
standardDescription: standardInfo?.helpText || "",
@@ -461,12 +517,12 @@ const Page = () => {
if (itemTemplateId) {
const standardId = `standards.ConditionalAccessTemplate.${itemTemplateId}`;
const standardInfo = standards.find(
- (s) => s.name === `standards.ConditionalAccessTemplate`
+ (s) => s.name === `standards.ConditionalAccessTemplate`,
);
// Find the tenant's value for this specific template
const currentTenantStandard = currentTenantData.find(
- (s) => s.standardId === standardId
+ (s) => s.standardId === standardId,
);
const standardObject = currentTenantObj?.[standardId];
const directStandardValue = standardObject?.Value;
@@ -509,8 +565,8 @@ const Page = () => {
complianceStatus: isOverridden
? "Overridden"
: isCompliant
- ? "Compliant"
- : "Non-Compliant",
+ ? "Compliant"
+ : "Non-Compliant",
complianceDetails:
standardInfo?.docsDescription || standardInfo?.helpText || "",
standardDescription: standardInfo?.helpText || "",
@@ -553,7 +609,7 @@ const Page = () => {
// Find the tenant's value for this template
const currentTenantStandard = currentTenantData.find(
- (s) => s.standardId === standardId
+ (s) => s.standardId === standardId,
);
const standardObject = currentTenantObj?.[standardId];
const directStandardValue = standardObject?.Value;
@@ -633,8 +689,8 @@ const Page = () => {
complianceStatus: isOverridden
? "Overridden"
: isCompliant
- ? "Compliant"
- : "Non-Compliant",
+ ? "Compliant"
+ : "Non-Compliant",
complianceDetails: standardInfo?.docsDescription || standardInfo?.helpText || "",
standardDescription: standardInfo?.helpText || "",
standardImpact: standardInfo?.impact || "Medium Impact",
@@ -674,44 +730,119 @@ const Page = () => {
actions.filter(
(action) =>
action?.value.toLowerCase() === "report" ||
- action?.value.toLowerCase() === "remediate"
+ action?.value.toLowerCase() === "remediate",
).length > 0;
// Find the tenant's value for this standard
const currentTenantStandard = currentTenantData.find(
- (s) => s.standardId === standardId
+ (s) => s.standardId === standardId,
);
// Check if the standard is directly in the tenant object (like "standards.AuditLog": {...})
const standardIdWithoutPrefix = standardId.replace("standards.", "");
const standardObject = currentTenantObj?.[standardId];
+ console.log(
+ "standardId:",
+ standardId,
+ "includes IntuneTag:",
+ standardId.includes("IntuneTag"),
+ );
+
+ // Debug logging for Intune tags
+ if (standardId.includes("IntuneTag") || standardId.includes("intuneTag")) {
+ console.log(`[${standardId}] standardObject:`, {
+ standardObject,
+ hasCurrentValue: standardObject?.CurrentValue !== undefined,
+ hasExpectedValue: standardObject?.ExpectedValue !== undefined,
+ Value: standardObject?.Value,
+ CurrentValue: standardObject?.CurrentValue,
+ ExpectedValue: standardObject?.ExpectedValue,
+ });
+ }
+
// Extract the actual value from the standard object (new data structure includes .Value property)
const directStandardValue = standardObject?.Value;
- // Determine compliance - use backend's logic: Value === true OR CurrentValue === ExpectedValue
+ // Determine compliance - prioritize Value field, then CurrentValue/ExpectedValue comparison
let isCompliant = false;
let reportingDisabled = !reportingEnabled;
- if (directStandardValue === true) {
- // Boolean true means compliant
+ // Helper function to compare values, handling arrays with order-independent comparison
+ const compareValues = (val1, val2) => {
+ // If both are arrays, compare as sets (order-independent)
+ if (Array.isArray(val1) && Array.isArray(val2)) {
+ if (val1.length !== val2.length) return false;
+ // Sort both arrays by their JSON representation for consistent comparison
+ const sorted1 = [...val1].sort((a, b) =>
+ JSON.stringify(a).localeCompare(JSON.stringify(b)),
+ );
+ const sorted2 = [...val2].sort((a, b) =>
+ JSON.stringify(a).localeCompare(JSON.stringify(b)),
+ );
+ return JSON.stringify(sorted1) === JSON.stringify(sorted2);
+ }
+ // For objects, sort keys to ensure consistent comparison
+ if (
+ typeof val1 === "object" &&
+ val1 !== null &&
+ typeof val2 === "object" &&
+ val2 !== null
+ ) {
+ const sortedVal1 = Object.keys(val1)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = val1[key];
+ return obj;
+ }, {});
+ const sortedVal2 = Object.keys(val2)
+ .sort()
+ .reduce((obj, key) => {
+ obj[key] = val2[key];
+ return obj;
+ }, {});
+ return JSON.stringify(sortedVal1) === JSON.stringify(sortedVal2);
+ }
+ // Otherwise use standard JSON comparison
+ return JSON.stringify(val1) === JSON.stringify(val2);
+ };
+
+ // FIRST: Check if CurrentValue and ExpectedValue exist and match (most reliable)
+ if (
+ standardObject?.CurrentValue !== undefined &&
+ standardObject?.ExpectedValue !== undefined
+ ) {
+ isCompliant = compareValues(
+ standardObject.CurrentValue,
+ standardObject.ExpectedValue,
+ );
+ // Debug logging for Intune tags
+ if (standardId.includes("IntuneTag") || standardId.includes("intuneTag")) {
+ console.log(`[${standardId}] Comparing CurrentValue vs ExpectedValue:`, {
+ CurrentValue: standardObject.CurrentValue,
+ ExpectedValue: standardObject.ExpectedValue,
+ isCompliant,
+ currentJSON: JSON.stringify(standardObject.CurrentValue),
+ expectedJSON: JSON.stringify(standardObject.ExpectedValue),
+ areEqual:
+ JSON.stringify(standardObject.CurrentValue) ===
+ JSON.stringify(standardObject.ExpectedValue),
+ });
+ }
+ }
+ // SECOND: Check if Value is explicitly true (compliant) or false (non-compliant)
+ else if (directStandardValue === true) {
isCompliant = true;
- } else if (standardObject?.CurrentValue && standardObject?.ExpectedValue) {
- // Compare CurrentValue and ExpectedValue (backend's comparison logic)
- isCompliant =
- JSON.stringify(standardObject.CurrentValue) ===
- JSON.stringify(standardObject.ExpectedValue);
- } else if (standardObject?.CurrentValue && standardObject?.ExpectedValue) {
- // Compare CurrentValue and ExpectedValue (backend's comparison logic)
- isCompliant =
- JSON.stringify(standardObject.CurrentValue) ===
- JSON.stringify(standardObject.ExpectedValue);
- } else if (directStandardValue !== undefined) {
- // For non-boolean values, use strict equality
+ } else if (directStandardValue === false) {
+ isCompliant = false;
+ }
+ // THIRD: For other non-boolean, non-null values, use strict equality with template settings
+ else if (directStandardValue !== undefined && directStandardValue !== null) {
isCompliant =
JSON.stringify(directStandardValue) === JSON.stringify(standardSettings);
- } else if (currentTenantStandard) {
- // Fall back to the previous logic if the standard is not directly in the tenant object
+ }
+ // FOURTH: Fall back to the previous logic if the standard is not directly in the tenant object
+ else if (currentTenantStandard) {
if (typeof standardSettings === "boolean" && standardSettings === true) {
isCompliant = currentTenantStandard.value === true;
} else {
@@ -725,8 +856,8 @@ const Page = () => {
const complianceStatus = reportingDisabled
? "Reporting Disabled"
: isCompliant
- ? "Compliant"
- : "Non-Compliant";
+ ? "Compliant"
+ : "Non-Compliant";
// Check if this standard is overridden by another template
const tenantTemplateId = standardObject?.TemplateId;
@@ -913,14 +1044,14 @@ const Page = () => {
const compliancePercentage =
allCount > 0
? Math.round(
- (compliantCount / (allCount - reportingDisabledCount - overriddenCount || 1)) * 100
+ (compliantCount / (allCount - reportingDisabledCount - overriddenCount || 1)) * 100,
)
: 0;
const missingLicensePercentage =
allCount > 0
? Math.round(
- (missingLicenseCount / (allCount - reportingDisabledCount - overriddenCount || 1)) * 100
+ (missingLicenseCount / (allCount - reportingDisabledCount - overriddenCount || 1)) * 100,
)
: 0;
@@ -1102,7 +1233,7 @@ const Page = () => {
query: query,
},
undefined,
- { shallow: true }
+ { shallow: true },
);
}}
sx={{ width: 300 }}
@@ -1198,8 +1329,8 @@ const Page = () => {
compliancePercentage === 100
? "success"
: compliancePercentage >= 50
- ? "warning"
- : "error"
+ ? "warning"
+ : "error"
}
/>
{
missingLicensePercentage === 0
? "success"
: missingLicensePercentage <= 25
- ? "warning"
- : "error"
+ ? "warning"
+ : "error"
}
/>
{
standard.complianceStatus === "Compliant"
? "success.main"
: standard.complianceStatus === "Overridden"
- ? "warning.main"
- : standard.complianceStatus === "Reporting Disabled"
- ? "grey.500"
- : "error.main",
+ ? "warning.main"
+ : standard.complianceStatus === "Reporting Disabled"
+ ? "grey.500"
+ : "error.main",
}}
>
{standard.complianceStatus === "Compliant" ? (
@@ -1481,78 +1612,94 @@ const Page = () => {
- {!standard.standardValue ? (
-
- This data has not yet been collected. Collect the data by pressing
- the report button on the top of the page.
-
- ) : (
+ {/* Show Expected Configuration with property-by-property breakdown */}
+ {standard.currentTenantValue?.ExpectedValue !== undefined ? (
-
-
- {standard.standardValue &&
- typeof standard.standardValue === "object" &&
- Object.keys(standard.standardValue).length > 0 ? (
- Object.entries(standard.standardValue).map(([key, value]) => (
-
+
+ Expected Configuration
+
+ {typeof standard.currentTenantValue.ExpectedValue === "object" &&
+ standard.currentTenantValue.ExpectedValue !== null ? (
+
+ {Object.entries(standard.currentTenantValue.ExpectedValue).map(
+ ([key, val]) => (
+
- {key}:
+ {key}
-
- {typeof value === "object" && value !== null
- ? value?.label || JSON.stringify(value)
- : value === true
- ? "Enabled"
- : value === false
- ? "Disabled"
- : String(value)}
-
+
+ {val !== undefined
+ ? JSON.stringify(val, null, 2)
+ : "Not set"}
+
+
- ))
- ) : (
-
- {standard.standardValue === true ? (
-
- This setting is configured correctly
-
- ) : standard.standardValue === false ? (
-
- This setting is not configured correctly
-
- ) : standard.standardValue !== undefined ? (
- typeof standard.standardValue === "object" ? (
- "No settings configured"
- ) : (
- String(standard.standardValue)
- )
- ) : (
-
- This setting is not configured, or data has not been
- collected. If you are getting this after data
- collection, the tenant might not be licensed for this
- feature
-
- )}
-
+ ),
)}
+
+ ) : (
+
+
+ {String(standard.currentTenantValue.ExpectedValue)}
+
-
+ )}
+ ) : (
+
+ This data has not yet been collected. Collect the data by pressing
+ the report button on the top of the page.
+
)}
@@ -1563,8 +1710,8 @@ const Page = () => {
standard.standardImpactColour === "info"
? "info"
: standard.standardImpactColour === "warning"
- ? "warning"
- : "error"
+ ? "warning"
+ : "error"
}
sx={{ mr: 1 }}
/>
@@ -1629,10 +1776,10 @@ const Page = () => {
standard.complianceStatus === "Compliant"
? "success.main"
: standard.complianceStatus === "Overridden"
- ? "warning.main"
- : standard.complianceStatus === "Reporting Disabled"
- ? "grey.500"
- : "error.main",
+ ? "warning.main"
+ : standard.complianceStatus === "Reporting Disabled"
+ ? "grey.500"
+ : "error.main",
borderRadius: "50%",
width: 8,
height: 8,
@@ -1652,7 +1799,7 @@ const Page = () => {
}
size="small"
label={`${new Date(
- standard.currentTenantValue.LastRefresh
+ standard.currentTenantValue.LastRefresh,
).toLocaleString()}`}
variant="outlined"
/>
@@ -1689,109 +1836,244 @@ const Page = () => {
) : standard.complianceStatus === "Compliant" ? (
<>
-
- This setting is configured correctly
-
- >
- ) : standard.currentTenantValue?.Value === false ? (
- <>
-
- This setting is not configured correctly
-
- {/* Show Current/Expected values for non-compliant standards */}
- {standard.currentTenantValue?.CurrentValue &&
- standard.currentTenantValue?.ExpectedValue && (
-
-
-
- Expected
-
-
+ {/* Show Current value property-by-property for compliant standards */}
+ {standard.currentTenantValue?.CurrentValue !== undefined ? (
+ typeof standard.currentTenantValue.CurrentValue ===
+ "object" &&
+ standard.currentTenantValue.CurrentValue !== null ? (
+
+
+ Current Configuration
+
+ {Object.entries(
+ standard.currentTenantValue.CurrentValue,
+ ).map(([key, val]) => (
+
- {JSON.stringify(
- standard.currentTenantValue.ExpectedValue,
- null,
- 2
- )}
+ {key}
+
+
+
+
+
+ {val !== undefined
+ ? JSON.stringify(val, null, 2)
+ : "Not set"}
+
+
-
-
+ ))}
+
+ ) : (
+
+
+ Current Configuration
+
+
- Current
+ {String(standard.currentTenantValue.CurrentValue)}
-
+
+
+ )
+ ) : null}
+ >
+ ) : (
+ <>
+ {standard.currentTenantValue?.Value === false && (
+
+ This setting is not configured correctly
+
+ )}
+ {/* Show Current value property-by-property for non-compliant standards */}
+ {standard.currentTenantValue?.CurrentValue !== undefined &&
+ (typeof standard.currentTenantValue.CurrentValue ===
+ "object" &&
+ standard.currentTenantValue.CurrentValue !== null ? (
+
+
+ Current Configuration
+
+ {Object.entries(
+ standard.currentTenantValue.CurrentValue,
+ ).map(([key, val]) => (
+
- {JSON.stringify(
- standard.currentTenantValue.CurrentValue,
- null,
- 2
- )}
+ {key}
+
+
+ {val !== undefined
+ ? JSON.stringify(val, null, 2)
+ : "Not set"}
+
+
+ ))}
+
+ ) : (
+
+
+ Current Configuration
+
+
+
+ {String(standard.currentTenantValue.CurrentValue)}
+
- )}
+ ))}
>
- ) : null}
+ )}
{/* Only show values if they're not simple true/false that's already covered by the alerts above */}
{!(
@@ -1810,7 +2092,7 @@ const Page = () => {
key === "Value" &&
(standard.currentTenantValue?.Value === true ||
standard.currentTenantValue?.Value === false)
- )
+ ),
)
.map(([key, value]) => {
const actualValue = key === "Value" ? value : value;
@@ -1858,8 +2140,8 @@ const Page = () => {
standard.complianceStatus === "Compliant"
? "success.main"
: isDifferent
- ? "error.main"
- : "inherit",
+ ? "error.main"
+ : "inherit",
fontWeight:
standard.complianceStatus === "Non-Compliant" &&
isDifferent
@@ -1902,10 +2184,10 @@ const Page = () => {
standard.complianceStatus === "Compliant"
? "success.main"
: standard.complianceStatus === "Overridden"
- ? "warning.main"
- : standard.complianceStatus === "Reporting Disabled"
- ? "text.secondary"
- : "error.main",
+ ? "warning.main"
+ : standard.complianceStatus === "Reporting Disabled"
+ ? "text.secondary"
+ : "error.main",
fontWeight:
standard.complianceStatus === "Non-Compliant"
? "medium"
@@ -1924,26 +2206,265 @@ const Page = () => {
standard.overridingTemplateId}
) : standard.complianceStatus === "Compliant" ? (
-
- This setting is configured correctly
-
- ) : standard.currentTenantValue?.Value === false ||
- standard.currentTenantValue === false ? (
-
- This setting is not configured correctly
-
- ) : standard.currentTenantValue !== undefined ? (
- String(
- standard.currentTenantValue?.Value !== undefined
- ? standard.currentTenantValue?.Value
- : standard.currentTenantValue
- )
+ <>
+ {/* Show Current value property-by-property in card view */}
+ {standard.currentTenantValue?.CurrentValue !== undefined ? (
+ typeof standard.currentTenantValue.CurrentValue ===
+ "object" &&
+ standard.currentTenantValue.CurrentValue !== null ? (
+
+
+ Current Configuration
+
+ {Object.entries(
+ standard.currentTenantValue.CurrentValue,
+ ).map(([key, val]) => (
+
+
+ {key}
+
+
+
+
+
+
+ {val !== undefined
+ ? JSON.stringify(val, null, 2)
+ : "Not set"}
+
+
+
+ ))}
+
+ ) : (
+
+
+ Current Configuration
+
+
+
+ {String(standard.currentTenantValue.CurrentValue)}
+
+
+
+ )
+ ) : null}
+ >
) : (
-
- This setting is not configured, or data has not been collected.
- If you are getting this after data collection, the tenant might
- not be licensed for this feature
-
+ <>
+ {(standard.currentTenantValue?.Value === false ||
+ standard.currentTenantValue === false) && (
+
+ This setting is not configured correctly
+
+ )}
+ {/* Show Current value property-by-property for non-compliant standards in card view */}
+ {standard.currentTenantValue?.CurrentValue !== undefined ? (
+ typeof standard.currentTenantValue.CurrentValue ===
+ "object" &&
+ standard.currentTenantValue.CurrentValue !== null ? (
+
+
+ Current Configuration
+
+ {Object.entries(
+ standard.currentTenantValue.CurrentValue,
+ ).map(([key, val]) => (
+
+
+ {key}
+
+
+
+ {val !== undefined
+ ? JSON.stringify(val, null, 2)
+ : "Not set"}
+
+
+
+ ))}
+
+ ) : (
+
+
+ Current Configuration
+
+
+
+ {String(standard.currentTenantValue.CurrentValue)}
+
+
+
+ )
+ ) : standard.currentTenantValue !== undefined &&
+ standard.currentTenantValue?.Value !== true &&
+ standard.currentTenantValue?.Value !== false ? (
+
+ {String(
+ standard.currentTenantValue?.Value !== undefined
+ ? standard.currentTenantValue?.Value
+ : standard.currentTenantValue,
+ )}
+
+ ) : standard.currentTenantValue === undefined ||
+ (standard.currentTenantValue?.Value === null &&
+ standard.currentTenantValue?.CurrentValue === undefined &&
+ standard.currentTenantValue?.ExpectedValue ===
+ undefined) ? (
+
+ This setting is not configured, or data has not been
+ collected. If you are getting this after data collection,
+ the tenant might not be licensed for this feature
+
+ ) : null}
+ >
)}
)}
diff --git a/src/pages/tenant/tools/tenantlookup/index.js b/src/pages/tenant/tools/tenantlookup/index.js
index 1678f428f818..08453771819d 100644
--- a/src/pages/tenant/tools/tenantlookup/index.js
+++ b/src/pages/tenant/tools/tenantlookup/index.js
@@ -84,7 +84,11 @@ const Page = () => {
Tenant Brand Name :{" "}
{getTenant.data?.GraphRequest?.federationBrandName
? getTenant.data?.GraphRequest?.federationBrandName
- : "N/A"}
+ : "Not Specified"}
+
+
+ Tenant Region:{" "}
+ {getTenant.data?.OpenIdConfig?.tenant_region_scope}