diff --git a/public/version.json b/public/version.json
index c0ab80971e47..ba547756572f 100644
--- a/public/version.json
+++ b/public/version.json
@@ -1,3 +1,3 @@
{
- "version": "7.3.1"
+ "version": "7.3.2"
}
diff --git a/src/components/CippComponents/CippAutocomplete.jsx b/src/components/CippComponents/CippAutocomplete.jsx
index 94b71886d005..4fb8c073086c 100644
--- a/src/components/CippComponents/CippAutocomplete.jsx
+++ b/src/components/CippComponents/CippAutocomplete.jsx
@@ -99,7 +99,7 @@ export const CippAutoComplete = (props) => {
setGetRequestInfo({
url: api.url,
data: {
- ...(!api.excludeTenantFilter ? { TenantFilter: currentTenant } : null),
+ ...(!api.excludeTenantFilter ? { tenantFilter: currentTenant } : null),
...api.data,
},
waiting: true,
diff --git a/src/components/CippComponents/CippExchangeActions.jsx b/src/components/CippComponents/CippExchangeActions.jsx
new file mode 100644
index 000000000000..329fb3492eed
--- /dev/null
+++ b/src/components/CippComponents/CippExchangeActions.jsx
@@ -0,0 +1,240 @@
+import {
+ EyeIcon,
+ TrashIcon,
+ MagnifyingGlassIcon,
+ PlayCircleIcon,
+} from "@heroicons/react/24/outline";
+import {
+ Archive,
+ MailOutline,
+ Person,
+ Room,
+ Visibility,
+ VisibilityOff,
+ PhonelinkLock,
+ Key,
+ PostAdd,
+ Add,
+} from "@mui/icons-material";
+import { useSettings } from "/src/hooks/use-settings.js";
+
+export const CippExchangeActions = () => {
+ // const tenant = useSettings().currentTenant;
+ return [
+ {
+ label: "Edit permissions",
+ link: "/identity/administration/users/user/exchange?userId=[ExternalDirectoryObjectId]",
+ color: "info",
+ icon: ,
+ },
+ {
+ label: "Research Compromised Account",
+ link: "/identity/administration/users/user/bec?userId=[ExternalDirectoryObjectId]",
+ color: "info",
+ icon: ,
+ },
+ {
+ label: "Send MFA Push",
+ type: "POST",
+ url: "/api/ExecSendPush",
+ data: {
+ UserEmail: "UPN",
+ },
+ confirmText: "Are you sure you want to send an MFA request?",
+ icon: ,
+ },
+ {
+ label: "Convert to User Mailbox",
+ type: "POST",
+ url: "/api/ExecConvertMailbox",
+ icon: ,
+ data: {
+ ID: "UPN",
+ MailboxType: "!Regular",
+ },
+ confirmText: "Are you sure you want to convert this mailbox to a user mailbox?",
+ condition: (row) => row.recipientTypeDetails !== "UserMailbox",
+ },
+ {
+ label: "Convert to Shared Mailbox",
+ type: "POST",
+ icon: ,
+ url: "/api/ExecConvertMailbox",
+ data: {
+ ID: "UPN",
+ MailboxType: "!Shared",
+ },
+ confirmText: "Are you sure you want to convert this mailbox to a shared mailbox?",
+ condition: (row) => row.recipientTypeDetails !== "SharedMailbox",
+ },
+ {
+ label: "Convert to Room Mailbox",
+ type: "POST",
+ url: "/api/ExecConvertMailbox",
+ icon: ,
+ data: {
+ ID: "UPN",
+ MailboxType: "!Room",
+ },
+ confirmText: "Are you sure you want to convert this mailbox to a room mailbox?",
+ condition: (row) => row.recipientTypeDetails !== "RoomMailbox",
+ },
+ {
+ //tested
+ label: "Enable Online Archive",
+ type: "POST",
+ icon: ,
+ url: "/api/ExecEnableArchive",
+ data: { ID: "Id", username: "UPN" },
+ confirmText: "Are you sure you want to enable the online archive for this user?",
+ multiPost: false,
+ condition: (row) => row.ArchiveGuid === "00000000-0000-0000-0000-000000000000",
+ },
+ {
+ label: "Enable Auto-Expanding Archive",
+ type: "POST",
+ icon: ,
+ url: "/api/ExecEnableAutoExpandingArchive",
+ data: { ID: "Id", username: "UPN" },
+ confirmText:
+ "Are you sure you want to enable auto-expanding archive for this user? The archive must already be enabled.",
+ multiPost: false,
+ condition: (row) => row.ArchiveGuid !== "00000000-0000-0000-0000-000000000000",
+ },
+ {
+ label: "Hide from Global Address List",
+ type: "POST",
+ url: "/api/ExecHideFromGAL",
+ icon: ,
+ data: {
+ ID: "UPN",
+ HidefromGAL: true,
+ },
+ confirmText:
+ "Are you sure you want to hide this mailbox from the global address list? This will not work if the user is AD Synced.",
+ condition: (row) => row.HiddenFromAddressListsEnabled === false,
+ },
+ {
+ label: "Unhide from Global Address List",
+ type: "POST",
+ url: "/api/ExecHideFromGAL",
+ icon: ,
+ data: {
+ ID: "UPN",
+ HidefromGAL: false,
+ },
+ confirmText:
+ "Are you sure you want to unhide this mailbox from the global address list? This will not work if the user is AD Synced.",
+ condition: (row) => row.HiddenFromAddressListsEnabled === true,
+ },
+ {
+ label: "Start Managed Folder Assistant",
+ type: "POST",
+ url: "/api/ExecStartManagedFolderAssistant",
+ icon: ,
+ data: {
+ ID: "ExchangeGuid",
+ UserPrincipalName: "UPN",
+ },
+ confirmText: "Are you sure you want to start the managed folder assistant for this user?",
+ },
+ {
+ label: "Delete Mailbox",
+ type: "POST",
+ icon: ,
+ url: "/api/RemoveUser",
+ data: { ID: "UPN" },
+ confirmText: "Are you sure you want to delete this mailbox?",
+ multiPost: false,
+ },
+ {
+ label: "Copy Sent Items to Shared Mailbox",
+ type: "POST",
+ url: "/api/ExecCopyForSent",
+ data: { ID: "UPN" },
+ confirmText: "Are you sure you want to enable Copy Sent Items to Shared Mailbox?",
+ icon: ,
+ condition: (row) =>
+ row.MessageCopyForSentAsEnabled === false && row.recipientTypeDetails === "SharedMailbox",
+ },
+ {
+ label: "Disable Copy Sent Items to Shared Mailbox",
+ type: "POST",
+ url: "/api/ExecCopyForSent",
+ data: { ID: "UPN", MessageCopyForSentAsEnabled: false },
+ confirmText: "Are you sure you want to disable Copy Sent Items to Shared Mailbox?",
+ icon: ,
+ condition: (row) =>
+ row.MessageCopyForSentAsEnabled === true && row.recipientTypeDetails === "SharedMailbox",
+ },
+ {
+ label: "Set mailbox locale",
+ type: "POST",
+ url: "/api/ExecSetMailboxLocale",
+ data: { user: "UPN", ProhibitSendQuota: true },
+ confirmText: "Enter a locale, e.g. en-US",
+ icon: ,
+ fields: [
+ {
+ label: "Locale",
+ name: "locale",
+ type: "textField",
+ placeholder: "e.g. en-US",
+ },
+ ],
+ },
+ {
+ label: "Set Send Quota",
+ type: "POST",
+ url: "/api/ExecSetMailboxQuota",
+ data: { user: "UPN", ProhibitSendQuota: true },
+ confirmText: "Enter a quota. e.g. 1000MB, 10GB,1TB",
+ icon: ,
+ fields: [
+ {
+ label: "Quota",
+ name: "quota",
+ type: "textField",
+ placeholder: "e.g. 1000MB, 10GB,1TB",
+ },
+ ],
+ },
+ {
+ label: "Set Send and Receive Quota",
+ type: "POST",
+ url: "/api/ExecSetMailboxQuota",
+ data: {
+ user: "UPN",
+ ProhibitSendReceiveQuota: true,
+ },
+ confirmText: "Enter a quota. e.g. 1000MB, 10GB,1TB",
+ icon: ,
+ fields: [
+ {
+ label: "Quota",
+ name: "quota",
+ type: "textField",
+ placeholder: "e.g. 1000MB, 10GB,1TB",
+ },
+ ],
+ },
+ {
+ label: "Set Quota Warning Level",
+ type: "POST",
+ url: "/api/ExecSetMailboxQuota",
+ data: { user: "UPN", IssueWarningQuota: true },
+ confirmText: "Enter a quota. e.g. 1000MB, 10GB,1TB",
+ icon: ,
+ fields: [
+ {
+ label: "Quota",
+ name: "quota",
+ type: "textField",
+ placeholder: "e.g. 1000MB, 10GB,1TB",
+ },
+ ],
+ },
+ ];
+};
+
+export default CippExchangeActions;
diff --git a/src/components/CippFormPages/CippAddEditUser.jsx b/src/components/CippFormPages/CippAddEditUser.jsx
index 5087d40456fa..9cee72637872 100644
--- a/src/components/CippFormPages/CippAddEditUser.jsx
+++ b/src/components/CippFormPages/CippAddEditUser.jsx
@@ -269,7 +269,7 @@ const CippAddEditUser = (props) => {
formControl={formControl}
/>
- {userSettingsDefaults?.userAttributes?.map((attribute, idx) => (
+ {userSettingsDefaults?.userAttributes?.filter((attribute) => attribute.value !== "sponsor").map((attribute, idx) => (
{
>
);
},
+ enableGlobalFilterModes: true,
});
useEffect(() => {
diff --git a/src/layouts/config.js b/src/layouts/config.js
index e7093b9f1883..812b5639f999 100644
--- a/src/layouts/config.js
+++ b/src/layouts/config.js
@@ -463,7 +463,7 @@ export const nativeMenuItems = [
),
items: [
{ title: "Application Settings", path: "/cipp/settings", roles: ["admin", "superadmin"] },
- { title: "Logbook", path: "/cipp/logs", roles: ["admin", "superadmin"] },
+ { title: "Logbook", path: "/cipp/logs", roles: ["editor", "admin", "superadmin"] },
{ title: "SAM Setup Wizard", path: "/onboarding", roles: ["admin", "superadmin"] },
{ title: "Integrations", path: "/cipp/integrations", roles: ["admin", "superadmin"] },
{
diff --git a/src/layouts/index.js b/src/layouts/index.js
index fa6e9812d5b6..c2f49483f74a 100644
--- a/src/layouts/index.js
+++ b/src/layouts/index.js
@@ -231,7 +231,7 @@ export const Layout = (props) => {
}}
>
- {currentTenant === "AllTenants" && !allTenantsSupport ? (
+ {(currentTenant === "AllTenants" || !currentTenant) && !allTenantsSupport ? (
diff --git a/src/pages/cipp/preferences.js b/src/pages/cipp/preferences.js
index 81fd6d446bbf..40ccac234133 100644
--- a/src/pages/cipp/preferences.js
+++ b/src/pages/cipp/preferences.js
@@ -35,6 +35,7 @@ const Page = () => {
{ value: "otherMails", label: "otherMails" },
{ value: "showInAddressList", label: "showInAddressList" },
{ value: "state", label: "state" },
+ { value: "city", label: "city" },
{ value: "sponsor", label: "sponsor" },
];
diff --git a/src/pages/cipp/scheduler/index.js b/src/pages/cipp/scheduler/index.js
index 97abcc20b602..81cf3213ed02 100644
--- a/src/pages/cipp/scheduler/index.js
+++ b/src/pages/cipp/scheduler/index.js
@@ -82,19 +82,20 @@ const Page = () => {
tenantInTitle={false}
title="Scheduled Tasks"
apiUrl={
- showHiddenJobs ? "/api/ListScheduledItems?ListHidden=True" : "/api/ListScheduledItems"
+ showHiddenJobs ? "/api/ListScheduledItems?ShowHidden=true" : "/api/ListScheduledItems"
}
queryKey={showHiddenJobs ? `ListScheduledItems-hidden` : `ListScheduledItems`}
simpleColumns={[
- "Name",
- "Tenant",
+ "ExecutedTime",
"TaskState",
+ "Tenant",
+ "Name",
+ "ScheduledTime",
"Command",
"Parameters",
"PostExecution",
"Recurrence",
- "ExecutedTime",
- "ScheduledTime",
+ "Results",
]}
actions={actions}
offCanvas={offCanvas}
diff --git a/src/pages/email/administration/mailboxes/index.js b/src/pages/email/administration/mailboxes/index.js
index c4014ca25d38..da5479b87fb4 100644
--- a/src/pages/email/administration/mailboxes/index.js
+++ b/src/pages/email/administration/mailboxes/index.js
@@ -2,243 +2,16 @@ import { Layout as DashboardLayout } from "/src/layouts/index.js";
import { CippTablePage } from "/src/components/CippComponents/CippTablePage.jsx";
import Link from "next/link";
import { Button } from "@mui/material";
-import {
- Archive,
- MailOutline,
- Person,
- Room,
- Visibility,
- VisibilityOff,
- PhonelinkLock,
- Key,
- PostAdd,
- Add,
-} from "@mui/icons-material";
-import { TrashIcon, MagnifyingGlassIcon, PlayCircleIcon } from "@heroicons/react/24/outline";
+import { Add } from "@mui/icons-material";
+import CippExchangeActions from "../../../../components/CippComponents/CippExchangeActions";
const Page = () => {
const pageTitle = "Mailboxes";
- // Define actions for mailboxes
- const actions = [
- {
- label: "Edit permissions",
- link: "/identity/administration/users/user/exchange?userId=[ExternalDirectoryObjectId]",
- color: "info",
- icon: ,
- },
- {
- label: "Research Compromised Account",
- link: "/identity/administration/users/user/bec?userId=[ExternalDirectoryObjectId]",
- color: "info",
- icon: ,
- },
- {
- label: "Send MFA Push",
- type: "POST",
- url: "/api/ExecSendPush",
- data: {
- UserEmail: "UPN",
- },
- confirmText: "Are you sure you want to send an MFA request?",
- icon: ,
- },
- {
- label: "Convert to User Mailbox",
- type: "POST",
- url: "/api/ExecConvertMailbox",
- icon: ,
- data: {
- ID: "UPN",
- MailboxType: "!Regular",
- },
- confirmText: "Are you sure you want to convert this mailbox to a user mailbox?",
- condition: (row) => row.recipientTypeDetails !== "UserMailbox",
- },
- {
- label: "Convert to Shared Mailbox",
- type: "POST",
- icon: ,
- url: "/api/ExecConvertMailbox",
- data: {
- ID: "UPN",
- MailboxType: "!Shared",
- },
- confirmText: "Are you sure you want to convert this mailbox to a shared mailbox?",
- condition: (row) => row.recipientTypeDetails !== "SharedMailbox",
- },
- {
- label: "Convert to Room Mailbox",
- type: "POST",
- url: "/api/ExecConvertMailbox",
- icon: ,
- data: {
- ID: "UPN",
- MailboxType: "!Room",
- },
- confirmText: "Are you sure you want to convert this mailbox to a room mailbox?",
- condition: (row) => row.recipientTypeDetails !== "RoomMailbox",
- },
- {
- //tested
- label: "Enable Online Archive",
- type: "POST",
- icon: ,
- url: "/api/ExecEnableArchive",
- data: { ID: "Id", username: "UPN" },
- confirmText: "Are you sure you want to enable the online archive for this user?",
- multiPost: false,
- condition: (row) => row.ArchiveGuid === "00000000-0000-0000-0000-000000000000",
- },
- {
- label: "Enable Auto-Expanding Archive",
- type: "POST",
- icon: ,
- url: "/api/ExecEnableAutoExpandingArchive",
- data: { ID: "Id", username: "UPN" },
- confirmText:
- "Are you sure you want to enable auto-expanding archive for this user? The archive must already be enabled.",
- multiPost: false,
- condition: (row) => row.ArchiveGuid !== "00000000-0000-0000-0000-000000000000",
- },
- {
- label: "Hide from Global Address List",
- type: "POST",
- url: "/api/ExecHideFromGAL",
- icon: ,
- data: {
- ID: "UPN",
- HidefromGAL: true,
- },
- confirmText:
- "Are you sure you want to hide this mailbox from the global address list? This will not work if the user is AD Synced.",
- condition: (row) => row.HiddenFromAddressListsEnabled === false,
- },
- {
- label: "Unhide from Global Address List",
- type: "POST",
- url: "/api/ExecHideFromGAL",
- icon: ,
- data: {
- ID: "UPN",
- },
- confirmText:
- "Are you sure you want to unhide this mailbox from the global address list? This will not work if the user is AD Synced.",
- condition: (row) => row.HiddenFromAddressListsEnabled === true,
- },
- {
- label: "Start Managed Folder Assistant",
- type: "POST",
- url: "/api/ExecStartManagedFolderAssistant",
- icon: ,
- data: {
- ID: "ExchangeGuid",
- UserPrincipalName: "UPN",
- },
- confirmText: "Are you sure you want to start the managed folder assistant for this user?",
- },
- {
- label: "Delete Mailbox",
- type: "POST",
- icon: ,
- url: "/api/RemoveUser",
- data: { ID: "UPN" },
- confirmText: "Are you sure you want to delete this mailbox?",
- multiPost: false,
- },
- {
- label: "Copy Sent Items to Shared Mailbox",
- type: "POST",
- url: "/api/ExecCopyForSent",
- data: { ID: "UPN" },
- confirmText: "Are you sure you want to enable Copy Sent Items to Shared Mailbox?",
- icon: ,
- condition: (row) =>
- row.MessageCopyForSentAsEnabled === false && row.recipientTypeDetails === "SharedMailbox",
- },
- {
- label: "Disable Copy Sent Items to Shared Mailbox",
- type: "POST",
- url: "/api/ExecCopyForSent",
- data: { ID: "UPN", MessageCopyForSentAsEnabled: false },
- confirmText: "Are you sure you want to disable Copy Sent Items to Shared Mailbox?",
- icon: ,
- condition: (row) =>
- row.MessageCopyForSentAsEnabled === true && row.recipientTypeDetails === "SharedMailbox",
- },
- {
- label: "Set mailbox locale",
- type: "POST",
- url: "/api/ExecSetMailboxLocale",
- data: { user: "UPN", ProhibitSendQuota: true },
- confirmText: "Enter a locale, e.g. en-US",
- icon: ,
- fields: [
- {
- label: "Locale",
- name: "locale",
- type: "textField",
- placeholder: "e.g. en-US",
- },
- ],
- },
- {
- label: "Set Send Quota",
- type: "POST",
- url: "/api/ExecSetMailboxQuota",
- data: { user: "UPN", ProhibitSendQuota: true },
- confirmText: "Enter a quota. e.g. 1000MB, 10GB,1TB",
- icon: ,
- fields: [
- {
- label: "Quota",
- name: "quota",
- type: "textField",
- placeholder: "e.g. 1000MB, 10GB,1TB",
- },
- ],
- },
- {
- label: "Set Send and Receive Quota",
- type: "POST",
- url: "/api/ExecSetMailboxQuota",
- data: {
- user: "UPN",
- ProhibitSendReceiveQuota: true,
- },
- confirmText: "Enter a quota. e.g. 1000MB, 10GB,1TB",
- icon: ,
- fields: [
- {
- label: "Quota",
- name: "quota",
- type: "textField",
- placeholder: "e.g. 1000MB, 10GB,1TB",
- },
- ],
- },
- {
- label: "Set Quota Warning Level",
- type: "POST",
- url: "/api/ExecSetMailboxQuota",
- data: { user: "UPN", IssueWarningQuota: true },
- confirmText: "Enter a quota. e.g. 1000MB, 10GB,1TB",
- icon: ,
- fields: [
- {
- label: "Quota",
- name: "quota",
- type: "textField",
- placeholder: "e.g. 1000MB, 10GB,1TB",
- },
- ],
- },
- ];
-
// Define off-canvas details
const offCanvas = {
extendedInfoFields: ["displayName", "UPN", "AdditionalEmailAddresses", "recipientTypeDetails"],
- actions: actions,
+ actions: CippExchangeActions(),
};
const filterList = [
@@ -278,7 +51,7 @@ const Page = () => {
{
const userSettingsDefaults = useSettings();
@@ -261,6 +262,8 @@ const Page = () => {
tabOptions={tabOptions}
title={title}
subtitle={subtitle}
+ actions={CippExchangeActions()}
+ actionsData={userRequest.data?.[0]?.MailboxActionsData}
isFetching={graphUserRequest.isLoading}
>
diff --git a/src/pages/identity/administration/users/user/index.jsx b/src/pages/identity/administration/users/user/index.jsx
index 0d8628fdd9d5..b36347b4a1f3 100644
--- a/src/pages/identity/administration/users/user/index.jsx
+++ b/src/pages/identity/administration/users/user/index.jsx
@@ -1,7 +1,7 @@
import { Layout as DashboardLayout } from "/src/layouts/index.js";
import { useSettings } from "/src/hooks/use-settings";
import { useRouter } from "next/router";
-import { ApiGetCall } from "/src/api/ApiCall";
+import { ApiGetCall, ApiPostCall } from "/src/api/ApiCall";
import CippFormSkeleton from "/src/components/CippFormPages/CippFormSkeleton";
import CalendarIcon from "@heroicons/react/24/outline/CalendarIcon";
import { AdminPanelSettings, Check, Group, Mail, Fingerprint, Launch } from "@mui/icons-material";
@@ -24,6 +24,7 @@ const CippMap = dynamic(() => import("/src/components/CippComponents/CippMap"),
import { Button, Dialog, DialogTitle, DialogContent, IconButton } from "@mui/material";
import { Close } from "@mui/icons-material";
import { CippPropertyList } from "../../../../../components/CippComponents/CippPropertyList";
+import { CippCodeBlock } from "../../../../../components/CippComponents/CippCodeBlock";
const SignInLogsDialog = ({ open, onClose, userId, tenantFilter }) => {
return (
@@ -85,33 +86,47 @@ const Page = () => {
waiting: waiting,
});
- const userMemberOf = ApiGetCall({
- url: "/api/ListGraphRequest",
- data: {
- Endpoint: `/users/${userId}/memberOf`,
- tenantFilter: userSettingsDefaults.currentTenant,
- $top: 99,
- },
- queryKey: `UserMemberOf-${userId}`,
+ const userBulkRequest = ApiPostCall({
+ urlfromdata: true,
});
- const MFARequest = ApiGetCall({
- url: "/api/ListGraphRequest",
- data: {
- Endpoint: `/users/${userId}/authentication/methods`,
- tenantFilter: userSettingsDefaults.currentTenant,
- noPagination: true,
- $top: 99,
- },
- queryKey: `MFA-${userId}`,
- waiting: waiting,
- });
+ useEffect(() => {
+ if (userId && userSettingsDefaults.currentTenant && !userBulkRequest.isSuccess) {
+ userBulkRequest.mutate({
+ url: "/api/ListGraphBulkRequest",
+ data: {
+ Requests: [
+ {
+ id: "userMemberOf",
+ url: `/users/${userId}/memberOf`,
+ method: "GET",
+ },
+ {
+ id: "mfaDevices",
+ url: `/users/${userId}/authentication/methods?$top=99`,
+ method: "GET",
+ },
+ {
+ id: "signInLogs",
+ url: `/auditLogs/signIns?$filter=(userId eq '${userId}')&$top=1`,
+ method: "GET",
+ },
+ ],
+ tenantFilter: userSettingsDefaults.currentTenant,
+ noPaginateIds: ["signInLogs"],
+ },
+ });
+ }
+ }, [userId, userSettingsDefaults.currentTenant, userBulkRequest.isSuccess]);
- const signInLogs = ApiGetCall({
- url: `/api/ListUserSigninLogs?UserId=${userId}&tenantFilter=${userSettingsDefaults.currentTenant}&top=1`,
- queryKey: `ListSignIns-${userId}`,
- waiting: waiting,
- });
+ const bulkData = userBulkRequest?.data?.data ?? [];
+ const signInLogsData = bulkData?.find((item) => item.id === "signInLogs");
+ const userMemberOfData = bulkData?.find((item) => item.id === "userMemberOf");
+ const mfaDevicesData = bulkData?.find((item) => item.id === "mfaDevices");
+
+ const signInLogs = signInLogsData?.body?.value || [];
+ const userMemberOf = userMemberOfData?.body?.value || [];
+ const mfaDevices = mfaDevicesData?.body?.value || [];
// Set the title and subtitle for the layout
const title = userRequest.isSuccess ? <>{userRequest.data?.[0]?.displayName}> : "Loading...";
@@ -138,15 +153,15 @@ const Page = () => {
icon: ,
text: (
+ color="muted"
+ style={{ paddingLeft: 0 }}
+ size="small"
+ href={`https://entra.microsoft.com/${userSettingsDefaults.currentTenant}/#view/Microsoft_AAD_UsersAndTenants/UserProfileMenuBlade/~/overview/userId/${userId}`}
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ View in Entra
+
),
},
]
@@ -159,8 +174,8 @@ const Page = () => {
let conditionalAccessPoliciesItems = [];
let mfaDevicesItems = [];
- if (signInLogs.isSuccess && signInLogs.data && signInLogs.data.length > 0) {
- const signInData = signInLogs.data[0];
+ if (signInLogs.length > 0) {
+ const signInData = signInLogs[0];
signInLogItem = {
id: 1,
@@ -330,12 +345,12 @@ const Page = () => {
},
];
}
- } else if (signInLogs.isError) {
+ } else if (signInLogsData?.status !== 200) {
signInLogItem = {
id: 1,
cardLabelBox: "!",
text: "Error loading sign-in logs. Do you have a P1 license?",
- subtext: signInLogs.error.message,
+ subtext: signInLogsData?.error?.message || "Unknown error",
statusColor: "error.main",
statusText: "Error",
propertyItems: [],
@@ -347,13 +362,13 @@ const Page = () => {
id: 1,
cardLabelBox: "!",
text: "Error loading conditional access policies. Do you have a P1 license?",
- subtext: signInLogs.error.message,
+ subtext: signInLogsData?.error?.message || "Unknown error",
statusColor: "error.main",
statusText: "Error",
propertyItems: [],
},
];
- } else if (signInLogs.isSuccess && (!signInLogs.data || signInLogs.data.length === 0)) {
+ } else if (signInLogs.length === 0) {
signInLogItem = {
id: 1,
cardLabelBox: "-",
@@ -362,7 +377,21 @@ const Page = () => {
"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: [],
+ propertyItems: [
+ {
+ label: "Error",
+ value: signInLogsData?.error?.message || "Unknown error",
+ },
+ {
+ label: "Inner Error",
+ value: (
+
+ ),
+ },
+ ],
};
conditionalAccessPoliciesItems = [
@@ -380,16 +409,14 @@ const Page = () => {
}
// Prepare MFA devices items
- if (MFARequest.isSuccess && MFARequest.data) {
- const mfaResults = MFARequest.data.Results || [];
-
+ if (mfaDevices.length > 0) {
// Exclude password authentication method
- const mfaDevices = mfaResults.filter(
+ const mfaDevicesFiltered = mfaDevices.filter(
(method) => method["@odata.type"] !== "#microsoft.graph.passwordAuthenticationMethod"
);
- if (mfaDevices.length > 0) {
- mfaDevicesItems = mfaDevices.map((device, index) => ({
+ if (mfaDevicesFiltered.length > 0) {
+ mfaDevicesItems = mfaDevicesFiltered.map((device, index) => ({
id: index,
cardLabelBox: {
cardLabelBoxHeader: ,
@@ -433,20 +460,37 @@ const Page = () => {
},
];
}
- } else if (MFARequest.isError) {
+ } else if (mfaDevicesData?.status !== 200) {
// Error fetching MFA devices
mfaDevicesItems = [
{
id: 1,
cardLabelBox: "!",
text: "Error loading MFA devices",
- subtext: MFARequest.error.message,
+ subtext: `Status code: ${mfaDevicesData?.status}`,
statusColor: "error.main",
statusText: "Error",
- propertyItems: [],
+ propertyItems: [
+ {
+ label: "Error",
+ value: mfaDevicesData?.body?.error?.message || "Unknown Error",
+ },
+ {
+ label: "Inner Error",
+ value: (
+
+ ),
+ },
+ ],
},
];
- } else if (MFARequest.isSuccess && (!MFARequest.data || !MFARequest.data.Results)) {
+ } else if (mfaDevices.length === 0) {
// No MFA devices data available
mfaDevicesItems = [
{
@@ -461,7 +505,7 @@ const Page = () => {
];
}
- const groupMembershipItems = userMemberOf.isSuccess
+ const groupMembershipItems = userMemberOf
? [
{
id: 1,
@@ -480,7 +524,7 @@ const Page = () => {
link: "/identity/administration/groups/edit?groupId=[id]",
},
],
- data: userMemberOf?.data?.Results.filter(
+ data: userMemberOf?.filter(
(item) => item?.["@odata.type"] === "#microsoft.graph.group"
),
simpleColumns: ["displayName", "groupTypes", "securityEnabled", "mailEnabled"],
@@ -489,7 +533,7 @@ const Page = () => {
]
: [];
- const roleMembershipItems = userMemberOf.isSuccess
+ const roleMembershipItems = userMemberOf
? [
{
id: 1,
@@ -501,7 +545,7 @@ const Page = () => {
table: {
title: "Admin Roles",
hideTitle: true,
- data: userMemberOf?.data?.Results.filter(
+ data: userMemberOf?.filter(
(item) => item?.["@odata.type"] === "#microsoft.graph.directoryRole"
),
simpleColumns: ["displayName", "description"],
@@ -539,30 +583,30 @@ const Page = () => {
Latest Logon
Applied Conditional Access Policies
0 ? true : false}
/>
Multi-Factor Authentication Devices
0 ? true : false}
/>
Memberships
0 ? true : false}
/>
0 ? true : false}
/>
diff --git a/src/pages/tenant/backup/backup-wizard/add.jsx b/src/pages/tenant/backup/backup-wizard/add.jsx
index 90d58127a11a..86ec994ca6c4 100644
--- a/src/pages/tenant/backup/backup-wizard/add.jsx
+++ b/src/pages/tenant/backup/backup-wizard/add.jsx
@@ -1,12 +1,12 @@
import React from "react";
import { Grid, Typography } from "@mui/material";
import { useForm } from "react-hook-form";
+import { omit } from "lodash";
import { Layout as DashboardLayout } from "/src/layouts/index.js";
import CippFormPage from "/src/components/CippFormPages/CippFormPage";
import CippFormComponent from "/src/components/CippComponents/CippFormComponent";
import { useSettings } from "/src/hooks/use-settings";
import { CippFormTenantSelector } from "../../../../components/CippComponents/CippFormTenantSelector";
-import { te } from "date-fns/locale";
const CreateBackup = () => {
const userSettingsDefaults = useSettings();
@@ -26,7 +26,6 @@ const CreateBackup = () => {
antiphishing: true,
CippWebhookAlerts: true,
CippScriptedAlerts: true,
- CippStandards: true,
},
});
@@ -45,7 +44,7 @@ const CreateBackup = () => {
TenantFilter: tenantFilter,
Name: `CIPP Backup - ${tenantFilter}`,
Command: { value: `New-CIPPBackup` },
- Parameters: { backupType: "Scheduled", ScheduledBackupValues: { ...values } },
+ Parameters: { backupType: "Scheduled", ScheduledBackupValues: { ...omit(values, ['tenantFilter']) } },
ScheduledTime: unixTime,
Recurrence: { value: "1d" },
};
@@ -168,14 +167,6 @@ const CreateBackup = () => {
formControl={formControl}
/>
-
-
-
{/* Add an empty Grid item to fill the second column */}
diff --git a/src/pages/tenant/backup/backup-wizard/restore.jsx b/src/pages/tenant/backup/backup-wizard/restore.jsx
index 2a332140b139..d7d8c1f16c37 100644
--- a/src/pages/tenant/backup/backup-wizard/restore.jsx
+++ b/src/pages/tenant/backup/backup-wizard/restore.jsx
@@ -1,11 +1,12 @@
import React, { useState, useEffect } from "react";
-import { Alert, Grid, Typography } from "@mui/material";
+import { Alert, Divider, Grid, Typography } from "@mui/material";
import { useForm, useWatch } from "react-hook-form";
import { Layout as DashboardLayout } from "/src/layouts/index.js";
import CippFormPage from "/src/components/CippFormPages/CippFormPage";
import CippFormComponent from "/src/components/CippComponents/CippFormComponent";
import { useSettings } from "/src/hooks/use-settings";
import { CippFormCondition } from "/src/components/CippComponents/CippFormCondition";
+import { Chip, Stack } from "@mui/material";
const RestoreBackupForm = () => {
const userSettingsDefaults = useSettings();
@@ -85,7 +86,6 @@ const RestoreBackupForm = () => {
antiphishing: values.antiphishing,
CippWebhookAlerts: values.CippWebhookAlerts,
CippScriptedAlerts: values.CippScriptedAlerts,
- CippStandards: values.CippStandards,
overwrite: values.overwrite,
},
},
@@ -95,6 +95,7 @@ const RestoreBackupForm = () => {
Email: values.email,
PSA: values.psa,
},
+ DisallowDuplicateName: true,
};
return shippedValues;
}}
@@ -104,7 +105,7 @@ const RestoreBackupForm = () => {
Use this form to restore a backup for a tenant. Please select the tenant, backup, and
restore options.
-
+
{/* Backup Selector */}
{
name="backup"
multiple={false}
api={{
- tenantFilter: tenantFilter,
url: "/api/ExecListBackup",
queryKey: `BackupList-${tenantFilter}`,
- labelField: (option) => `${option.RowKey}`,
- valueField: "RowKey",
+ labelField: (option) => {
+ const match = option.BackupName.match(/.*_(\d{4}-\d{2}-\d{2})-(\d{2})(\d{2})/);
+ return match ? `${match[1]} @ ${match[2]}:${match[3]}` : option.BackupName;
+ },
+ valueField: "BackupName",
data: {
Type: "Scheduled",
- TenantFilter: tenantFilter,
+ NameOnly: true,
},
}}
formControl={formControl}
+ required={true}
+ validators={{
+ validate: (value) => !!value || "Please select a backup",
+ }}
/>
@@ -210,12 +217,6 @@ const RestoreBackupForm = () => {
name="CippScriptedAlerts"
formControl={formControl}
/>
-
{/* Overwrite Existing Entries */}
@@ -262,38 +263,46 @@ const RestoreBackupForm = () => {
-
+
+
+
{/* Review and Confirm */}
- Review and Confirm
-
+ Review and Confirm
+
Please review the selected options before submitting.
Selected Tenant:
- {tenantFilter}
+
+ {tenantFilter}
+
Selected Backup:
-
+
{formControl.watch("backup")?.label || "None selected"}
Overwrite Existing Configuration:
- {formControl.watch("overwrite") ? "Yes" : "No"}
+
+ {formControl.watch("overwrite") ? "Yes" : "No"}
+
+
Send Results To:
-
- {formControl.watch("webhook") && "Webhook "}
- {formControl.watch("email") && "E-mail "}
- {formControl.watch("psa") && "PSA "}
- {!formControl.watch("webhook") &&
- !formControl.watch("email") &&
- !formControl.watch("psa") &&
- "None"}
+
+
+ {formControl.watch("webhook") && }
+ {formControl.watch("email") && }
+ {formControl.watch("psa") && }
+ {!formControl.watch("webhook") &&
+ !formControl.watch("email") &&
+ !formControl.watch("psa") && }
+
diff --git a/src/pages/tenant/reports/list-csp-licenses/index.jsx b/src/pages/tenant/reports/list-csp-licenses/index.jsx
index 9e6264df4c74..b046b6ea275c 100644
--- a/src/pages/tenant/reports/list-csp-licenses/index.jsx
+++ b/src/pages/tenant/reports/list-csp-licenses/index.jsx
@@ -93,7 +93,7 @@ const Page = () => {
simpleColumns={simpleColumns}
cardButton={
<>
- }>
+ }>
Add Subscription
>
diff --git a/src/utils/get-cipp-formatting.js b/src/utils/get-cipp-formatting.js
index 25b1cd58c7ec..48e57d972f1a 100644
--- a/src/utils/get-cipp-formatting.js
+++ b/src/utils/get-cipp-formatting.js
@@ -219,6 +219,24 @@ export const getCippFormatting = (data, cellName, type, canReceive) => {
}
}
+ if (cellName === "PostExecution") {
+ const values = data ? data?.split(",").map((item) => item.trim()) : [];
+ if (values.length > 0) {
+ return isText
+ ? data
+ : values.map((value, index) => (
+
+ ));
+ }
+ }
+
if (cellName === "ClientId" || cellName === "role") {
return isText ? data : ;
}