From d70ad08be330649ce695933f3f1e0fede4c8264e Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 18 Nov 2024 00:25:14 +0100 Subject: [PATCH] exchange window --- .../CippCards/CippExchangeInfoCard.jsx | 193 +++++++++++ src/components/linearProgressWithLabel.jsx | 6 +- src/components/property-list-item.js | 2 +- .../administration/users/user/exchange.jsx | 320 ++---------------- 4 files changed, 219 insertions(+), 302 deletions(-) create mode 100644 src/components/CippCards/CippExchangeInfoCard.jsx diff --git a/src/components/CippCards/CippExchangeInfoCard.jsx b/src/components/CippCards/CippExchangeInfoCard.jsx new file mode 100644 index 000000000000..c08c92a1442f --- /dev/null +++ b/src/components/CippCards/CippExchangeInfoCard.jsx @@ -0,0 +1,193 @@ +import PropTypes from "prop-types"; +import { Card, CardHeader, Divider, Skeleton, Chip } from "@mui/material"; +import { PropertyList } from "/src/components/property-list"; +import { PropertyListItem } from "/src/components/property-list-item"; +import { getCippFormatting } from "../../utils/get-cipp-formatting"; +import { Check as CheckIcon, Close as CloseIcon } from "@mui/icons-material"; +import { LinearProgressWithLabel } from "../linearProgressWithLabel"; +import { getCippTranslation } from "../../utils/get-cipp-translation"; + +export const CippExchangeInfoCard = (props) => { + const { exchangeData, isFetching = false, ...other } = props; + + // Define the protocols array + const protocols = [ + { name: "EWS", enabled: exchangeData?.EWSEnabled }, + { name: "MAPI", enabled: exchangeData?.MailboxMAPIEnabled }, + { name: "OWA", enabled: exchangeData?.MailboxOWAEnabled }, + { name: "IMAP", enabled: exchangeData?.MailboxImapEnabled }, + { name: "POP", enabled: exchangeData?.MailboxPopEnabled }, + { name: "ActiveSync", enabled: exchangeData?.MailboxActiveSyncEnabled }, + ]; + + return ( + + + + + + ) : ( + getCippTranslation(exchangeData?.RecipientTypeDetails) || "N/A" + ) + } + /> + + ) : exchangeData?.TotalItemSize != null ? ( + + ) : ( + "N/A" + ) + } + /> + + ) : ( + getCippFormatting(exchangeData?.HiddenFromAddressLists, "HiddenFromAddressLists") + ) + } + /> + + ) : ( + getCippFormatting(exchangeData?.ForwardAndDeliver, "ForwardAndDeliver") + ) + } + /> + + ) : ( + exchangeData?.ForwardingAddress || "N/A" + ) + } + /> + + ) : ( + getCippFormatting(exchangeData?.ArchiveMailBox, "ArchiveMailBox") + ) + } + /> + + ) : ( + getCippFormatting(exchangeData?.AutoExpandingArchive, "AutoExpandingArchive") + ) + } + /> + + ) : exchangeData?.TotalArchiveItemSize != null ? ( + `${exchangeData.TotalArchiveItemSize} GB` + ) : ( + "N/A" + ) + } + /> + + ) : exchangeData?.TotalArchiveItemCount != null ? ( + exchangeData.TotalArchiveItemCount + ) : ( + "N/A" + ) + } + /> + + ) : ( + getCippFormatting(exchangeData?.LitigationHold, "LitigationHold") + ) + } + /> + {/* Combine protocols into a single PropertyListItem */} + + ) : ( +
+ {protocols.map((protocol) => ( + : } + color={protocol.enabled ? "success" : "default"} + variant="outlined" + size="small" + sx={{ mr: 1, mb: 1 }} + /> + ))} +
+ ) + } + /> + + ) : ( + getCippFormatting(exchangeData?.BlockedForSpam, "BlockedForSpam") + ) + } + /> +
+
+ ); +}; + +CippExchangeInfoCard.propTypes = { + exchangeData: PropTypes.object, + isFetching: PropTypes.bool, +}; diff --git a/src/components/linearProgressWithLabel.jsx b/src/components/linearProgressWithLabel.jsx index 5f2de45f3be4..b12d467287fa 100644 --- a/src/components/linearProgressWithLabel.jsx +++ b/src/components/linearProgressWithLabel.jsx @@ -6,11 +6,7 @@ export const LinearProgressWithLabel = (props) => { - - - {`${Math.round(props.value)}%`} - - + {`${Math.round(props.value)}%`} ); }; diff --git a/src/components/property-list-item.js b/src/components/property-list-item.js index 88be53cfe0c9..70318631bf36 100644 --- a/src/components/property-list-item.js +++ b/src/components/property-list-item.js @@ -78,9 +78,9 @@ export const PropertyListItem = (props) => { } sx={{ alignItems: "flex-start", - display: "flex", flexDirection: align === "vertical" ? "column" : "row", my: 0, + width: "100%", }} /> diff --git a/src/pages/identity/administration/users/user/exchange.jsx b/src/pages/identity/administration/users/user/exchange.jsx index 781e6e4150be..ccd63c11bfb3 100644 --- a/src/pages/identity/administration/users/user/exchange.jsx +++ b/src/pages/identity/administration/users/user/exchange.jsx @@ -4,16 +4,16 @@ import { useRouter } from "next/router"; import { ApiGetCall } from "/src/api/ApiCall"; import CippFormSkeleton from "/src/components/CippFormPages/CippFormSkeleton"; import CalendarIcon from "@heroicons/react/24/outline/CalendarIcon"; -import { Check, Mail } from "@mui/icons-material"; +import { Mail } from "@mui/icons-material"; import { HeaderedTabbedLayout } from "../../../../../layouts/HeaderedTabbedLayout"; import tabOptions from "./tabOptions"; import ReactTimeAgo from "react-time-ago"; import { CippCopyToClipBoard } from "../../../../../components/CippComponents/CippCopyToClipboard"; import { Box, Stack } from "@mui/system"; import Grid from "@mui/material/Grid2"; -import { CippUserInfoCard } from "../../../../../components/CippCards/CippUserInfoCard"; import { Typography } from "@mui/material"; import { CippBannerListCard } from "../../../../../components/CippCards/CippBannerListCard"; +import { CippExchangeInfoCard } from "../../../../../components/CippCards/CippExchangeInfoCard"; const Page = () => { const userSettingsDefaults = useSettings(); @@ -21,39 +21,34 @@ const Page = () => { const { userId } = router.query; const userRequest = ApiGetCall({ - url: `/api/ListUsers?UserId=${userId}&tenantFilter=${userSettingsDefaults.currentTenant}`, - queryKey: `ListUsers-${userId}`, + url: `/api/ListUserMailboxDetails?UserId=${userId}&tenantFilter=${userSettingsDefaults.currentTenant}`, + queryKey: `Mailbox-${userId}`, }); - - const MFARequest = ApiGetCall({ - url: "/api/ListGraphRequest", - data: { - Endpoint: `/users/${userId}/authentication/methods`, - tenantFilter: userSettingsDefaults.currentTenant, - noPagination: true, - $top: 99, - }, - queryKey: `MFA-${userId}`, - }); - - const signInLogs = ApiGetCall({ - url: `/api/ListUserSigninLogs?UserId=${userId}&tenantFilter=${userSettingsDefaults.currentTenant}&top=1`, - queryKey: `ListSignIns-${userId}`, - }); - - const title = userRequest.isSuccess ? userRequest.data?.[0]?.displayName : "Loading..."; + const title = userRequest.isSuccess + ? userRequest.data?.[0]?.Mailbox?.[0]?.UserPrincipalName + : "Loading..."; const subtitle = userRequest.isSuccess ? [ { icon: , - text: , + text: ( + + ), }, { icon: , text: ( <> - Created: {" "} + Created:{" "} + {userRequest.data?.[0]?.Mailbox?.[0]?.WhenCreated ? ( + + ) : ( + "Unknown" + )} ), }, @@ -62,261 +57,6 @@ const Page = () => { const data = userRequest.data?.[0]; - let signInLogItem = null; - let conditionalAccessPoliciesItems = []; - let mfaDevicesItems = []; - - if (signInLogs.isSuccess && signInLogs.data && signInLogs.data.length > 0) { - const signInData = signInLogs.data[0]; - - signInLogItem = { - id: 1, - cardLabelBox: { - cardLabelBoxHeader: new Date(signInData.createdDateTime).getDate().toString(), - cardLabelBoxText: new Date(signInData.createdDateTime).toLocaleString("default", { - month: "short", - year: "numeric", - }), - }, - text: `Login ${signInData.status.errorCode === 0 ? "successful" : "failed"} from ${ - signInData.ipAddress || "unknown location" - }`, - subtext: `Logged into application ${signInData.resourceDisplayName || "Unknown Application"}`, - statusColor: signInData.status.errorCode === 0 ? "success.main" : "error.main", - statusText: signInData.status.errorCode === 0 ? "Success" : "Failed", - propertyItems: [ - { - label: "Client App Used", - value: signInData.clientAppUsed || "N/A", - }, - { - label: "Device Detail", - value: - signInData.deviceDetail?.operatingSystem || signInData.deviceDetail?.browser || "N/A", - }, - { - label: "MFA Type used", - value: signInData.mfaDetail?.authMethod || "N/A", - }, - { - label: "Additional Details", - value: signInData.status?.additionalDetails || "N/A", - }, - ], - }; - - if ( - signInData.appliedConditionalAccessPolicies && - Array.isArray(signInData.appliedConditionalAccessPolicies) - ) { - const appliedPolicies = signInData.appliedConditionalAccessPolicies.filter( - (policy) => policy.result === "success" - ); - - if (appliedPolicies.length > 0) { - conditionalAccessPoliciesItems = appliedPolicies.map((policy) => ({ - id: policy.id, - cardLabelBox: { - cardLabelBoxHeader: new Date(signInData.createdDateTime).getDate().toString(), - cardLabelBoxText: new Date(signInData.createdDateTime).toLocaleString("default", { - month: "short", - year: "numeric", - }), - }, - text: policy.displayName, - subtext: `Policy applied: ${policy.result}`, - statusColor: "success.main", - statusText: "Applied", - propertyItems: [ - { - label: "Grant Controls", - value: - policy.enforcedGrantControls.length > 0 - ? policy.enforcedGrantControls.join(", ") - : "None", - }, - { - label: "Session Controls", - value: - policy.enforcedSessionControls.length > 0 - ? policy.enforcedSessionControls.join(", ") - : "None", - }, - { - label: "Conditions Satisfied", - value: policy.conditionsSatisfied || "N/A", - }, - ], - })); - } else { - conditionalAccessPoliciesItems = [ - { - id: 1, - cardLabelBox: { - cardLabelBoxHeader: new Date(signInData.createdDateTime).getDate().toString(), - cardLabelBoxText: new Date(signInData.createdDateTime).toLocaleString("default", { - month: "short", - year: "numeric", - }), - }, - text: "No conditional access policies applied", - subtext: "No conditional access policies were applied during this sign-in.", - statusColor: "warning.main", - statusText: "No Policies Applied", - propertyItems: [], - }, - ]; - } - } else { - conditionalAccessPoliciesItems = [ - { - id: 1, - cardLabelBox: { - cardLabelBoxHeader: new Date(signInData.createdDateTime).getDate().toString(), - cardLabelBoxText: new Date(signInData.createdDateTime).toLocaleString("default", { - month: "short", - year: "numeric", - }), - }, - text: "No conditional access policies available", - subtext: "No conditional access policies data is available for this sign-in.", - statusColor: "warning.main", - statusText: "No Data", - propertyItems: [], - }, - ]; - } - } else if (signInLogs.isError) { - signInLogItem = { - id: 1, - cardLabelBox: "!", - text: "Error loading sign-in logs. Do you have a P1 license?", - subtext: signInLogs.error.message, - statusColor: "error.main", - statusText: "Error", - propertyItems: [], - }; - - // Handle error for conditional access policies - conditionalAccessPoliciesItems = [ - { - id: 1, - cardLabelBox: "!", - text: "Error loading conditional access policies. Do you have a P1 license?", - subtext: signInLogs.error.message, - statusColor: "error.main", - statusText: "Error", - propertyItems: [], - }, - ]; - } else if (signInLogs.isSuccess && (!signInLogs.data || signInLogs.data.length === 0)) { - signInLogItem = { - id: 1, - cardLabelBox: "-", - text: "No sign-in logs available", - subtext: - "There are no sign-in logs for this user, or you do not have a P1 license to detect this data.", - statusColor: "warning.main", - statusText: "No Data", - propertyItems: [], - }; - - conditionalAccessPoliciesItems = [ - { - id: 1, - cardLabelBox: "-", - text: "No conditional access policies available", - subtext: - "There are no conditional access policies for this user, or you do not have a P1 license to detect this data.", - statusColor: "warning.main", - statusText: "No Data", - propertyItems: [], - }, - ]; - } - - // Prepare MFA devices items - if (MFARequest.isSuccess && MFARequest.data) { - const mfaResults = MFARequest.data.Results || []; - - // Exclude password authentication method - const mfaDevices = mfaResults.filter( - (method) => method["@odata.type"] !== "#microsoft.graph.passwordAuthenticationMethod" - ); - - if (mfaDevices.length > 0) { - mfaDevicesItems = mfaDevices.map((device, index) => ({ - id: index, - cardLabelBox: { - cardLabelBoxHeader: , - }, - text: device.displayName || "MFA Device", - subtext: device.deviceTag || device.clientAppName || "Unknown device", - statusColor: "success.main", - statusText: "Enabled", - propertyItems: [ - { - label: "Device Name", - value: device.displayName || "N/A", - }, - { - label: "App Version", - value: device.phoneAppVersion || "N/A", - }, - { - label: "Created Date", - value: device.createdDateTime - ? new Date(device.createdDateTime).toLocaleString() - : "N/A", - }, - { - label: "Authentication Method", - value: device["@odata.type"].split(".").pop() || "N/A", - }, - ], - })); - } else { - // No MFA devices other than password - mfaDevicesItems = [ - { - id: 1, - cardLabelBox: "-", - text: "No MFA devices available", - subtext: "The user does not have any MFA devices registered.", - statusColor: "warning.main", - statusText: "No Devices", - propertyItems: [], - }, - ]; - } - } else if (MFARequest.isError) { - // Error fetching MFA devices - mfaDevicesItems = [ - { - id: 1, - cardLabelBox: "!", - text: "Error loading MFA devices", - subtext: MFARequest.error.message, - statusColor: "error.main", - statusText: "Error", - propertyItems: [], - }, - ]; - } else if (MFARequest.isSuccess && (!MFARequest.data || !MFARequest.data.Results)) { - // No MFA devices data available - mfaDevicesItems = [ - { - id: 1, - cardLabelBox: "-", - text: "No MFA devices available", - subtext: "The user does not have any MFA devices registered.", - statusColor: "warning.main", - statusText: "No Devices", - propertyItems: [], - }, - ]; - } - return ( { > - + - Latest Logon - - Applied Conditional Access Policies - 0 ? true : false} - /> - Multi-Factor Authentication Devices + Mailbox permissions 0 ? true : false} + isFetching={userRequest.isLoading} + items={[]} + isCollapsible={false} />