diff --git a/package.json b/package.json
index 06670325843f..05a3468c52e4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cipp",
- "version": "10.2.0",
+ "version": "10.2.1",
"author": "CIPP Contributors",
"homepage": "https://cipp.app/",
"bugs": {
diff --git a/public/version.json b/public/version.json
index 7e488263a60c..6fafb4fbb418 100644
--- a/public/version.json
+++ b/public/version.json
@@ -1,3 +1,3 @@
{
- "version": "10.2.0"
+ "version": "10.2.1"
}
\ No newline at end of file
diff --git a/src/components/CippComponents/CippAddTenantGroupDrawer.jsx b/src/components/CippComponents/CippAddTenantGroupDrawer.jsx
index 75804c15f89c..a82e0fd3f791 100644
--- a/src/components/CippComponents/CippAddTenantGroupDrawer.jsx
+++ b/src/components/CippComponents/CippAddTenantGroupDrawer.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import { useState, useEffect } from "react";
import { Button, Box } from "@mui/material";
import { useForm, useFormState } from "react-hook-form";
import { GroupAdd } from "@mui/icons-material";
@@ -6,7 +6,6 @@ import { CippOffCanvas } from "./CippOffCanvas";
import { CippApiResults } from "./CippApiResults";
import { ApiPostCall } from "../../api/ApiCall";
import CippAddEditTenantGroups from "./CippAddEditTenantGroups";
-import { getCippValidator } from "../../utils/get-cipp-validator";
export const CippAddTenantGroupDrawer = ({
buttonText = "Add Tenant Group",
diff --git a/src/components/CippFormPages/CippAddEditUser.jsx b/src/components/CippFormPages/CippAddEditUser.jsx
index edcc5e7cb73c..b479cacd197a 100644
--- a/src/components/CippFormPages/CippAddEditUser.jsx
+++ b/src/components/CippFormPages/CippAddEditUser.jsx
@@ -112,6 +112,21 @@ const CippAddEditUser = (props) => {
return username.toLowerCase();
};
+ const validateOtherMails = (value) => {
+ if (!value || (Array.isArray(value) && value.length === 0)) {
+ return true;
+ }
+
+ const emailList = (Array.isArray(value) ? value.join(",") : value)
+ .split(",")
+ .map((email) => email.trim())
+ .filter(Boolean);
+
+ const invalidEmail = emailList.find((email) => getCippValidator(email, "email") !== true);
+
+ return !invalidEmail || `This is not a valid email: ${invalidEmail}`;
+ };
+
useEffect(() => {
//if watch.firstname changes, and watch.lastname changes, set displayname to firstname + lastname
if (watcher.givenName && watcher.surname && formType === "add") {
@@ -331,7 +346,6 @@ const CippAddEditUser = (props) => {
setDisplayNameManuallySet(true);
}}
required={true}
- validators={{ required: "Display Name is required" }}
/>
@@ -356,7 +370,6 @@ const CippAddEditUser = (props) => {
setUsernameManuallySet(true);
}}
required={true}
- validators={{ required: "Username is required" }}
/>
@@ -603,10 +616,10 @@ const CippAddEditUser = (props) => {
!value || getCippValidator(value, "email") }}
+ validators={{ validate: validateOtherMails }}
/>
{userSettingsDefaults?.userAttributes
diff --git a/src/layouts/config.js b/src/layouts/config.js
index 78a9cd4ed9d5..41c2ce0ed418 100644
--- a/src/layouts/config.js
+++ b/src/layouts/config.js
@@ -741,6 +741,11 @@ export const nativeMenuItems = [
path: "/email/reports/calendar-permissions",
permissions: ["Exchange.Mailbox.*"],
},
+ {
+ title: "Mailbox Forwarding",
+ path: "/email/reports/mailbox-forwarding",
+ permissions: ["Exchange.Mailbox.*"],
+ },
{
title: "Anti-Phishing Filters",
path: "/email/reports/antiphishing-filters",
diff --git a/src/pages/email/reports/mailbox-forwarding/index.js b/src/pages/email/reports/mailbox-forwarding/index.js
new file mode 100644
index 000000000000..008637df1a97
--- /dev/null
+++ b/src/pages/email/reports/mailbox-forwarding/index.js
@@ -0,0 +1,116 @@
+import { Layout as DashboardLayout } from "../../../../layouts/index.js";
+import { CippTablePage } from "../../../../components/CippComponents/CippTablePage.jsx";
+import { useState } from "react";
+import { Button, 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";
+import { CippQueueTracker } from "../../../../components/CippTable/CippQueueTracker";
+
+const Page = () => {
+ const currentTenant = useSettings().currentTenant;
+ const syncDialog = useDialog();
+ const [syncQueueId, setSyncQueueId] = useState(null);
+
+ const isAllTenants = currentTenant === "AllTenants";
+
+ const columns = [
+ ...(isAllTenants ? ["Tenant"] : []),
+ "UPN",
+ "DisplayName",
+ "RecipientTypeDetails",
+ "ForwardingType",
+ "ForwardTo",
+ "DeliverToMailboxAndForward",
+ "CacheTimestamp",
+ ];
+
+ const apiData = {
+ UseReportDB: true,
+ };
+
+ const filters = [
+ {
+ filterName: "External Forwarding",
+ value: [{ id: "ForwardingType", value: "External" }],
+ type: "column",
+ },
+ {
+ filterName: "Internal Forwarding",
+ value: [{ id: "ForwardingType", value: "Internal" }],
+ type: "column",
+ },
+ ];
+
+ const pageActions = [
+
+
+
+
+
+
+
+
+ ,
+ ];
+
+ return (
+ <>
+ {currentTenant && currentTenant !== "" ? (
+
+ ) : (
+ Please select a tenant to view mailbox forwarding settings.
+ )}
+ {
+ if (result?.Metadata?.QueueId) {
+ setSyncQueueId(result.Metadata.QueueId);
+ }
+ },
+ }}
+ />
+ >
+ );
+};
+
+Page.getLayout = (page) => {page};
+
+export default Page;
diff --git a/src/pages/identity/administration/users/add.jsx b/src/pages/identity/administration/users/add.jsx
index 28606efc90ba..46a8c07fac61 100644
--- a/src/pages/identity/administration/users/add.jsx
+++ b/src/pages/identity/administration/users/add.jsx
@@ -2,13 +2,13 @@ import { Box } from "@mui/material";
import CippFormPage from "../../../../components/CippFormPages/CippFormPage";
import { Layout as DashboardLayout } from "../../../../layouts/index.js";
import { useForm, useWatch } from "react-hook-form";
-import { CippFormUserSelector } from "../../../../components/CippComponents/CippFormUserSelector";
import { useSettings } from "../../../../hooks/use-settings";
import { useEffect } from "react";
import CippAddEditUser from "../../../../components/CippFormPages/CippAddEditUser";
const Page = () => {
const userSettingsDefaults = useSettings();
+ const tenantDomain = useSettings().currentTenant;
const formControl = useForm({
mode: "onBlur",
@@ -54,6 +54,7 @@ const Page = () => {
title="User"
backButtonTitle="User Overview"
postUrl="/api/AddUser"
+ relatedQueryKeys={`Users - ${tenantDomain}`}
>