Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cipp",
"version": "10.2.0",
"version": "10.2.1",
"author": "CIPP Contributors",
"homepage": "https://cipp.app/",
"bugs": {
Expand Down
2 changes: 1 addition & 1 deletion public/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "10.2.0"
"version": "10.2.1"
}
3 changes: 1 addition & 2 deletions src/components/CippComponents/CippAddTenantGroupDrawer.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
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";
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",
Expand Down
21 changes: 17 additions & 4 deletions src/components/CippFormPages/CippAddEditUser.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down Expand Up @@ -331,7 +346,6 @@ const CippAddEditUser = (props) => {
setDisplayNameManuallySet(true);
}}
required={true}
validators={{ required: "Display Name is required" }}
/>
</Grid>
<Grid size={{ md: 6, xs: 12 }}>
Expand All @@ -356,7 +370,6 @@ const CippAddEditUser = (props) => {
setUsernameManuallySet(true);
}}
required={true}
validators={{ required: "Username is required" }}
/>
</Grid>
<Grid size={{ md: 6, xs: 12 }}>
Expand Down Expand Up @@ -603,10 +616,10 @@ const CippAddEditUser = (props) => {
<CippFormComponent
type="textField"
fullWidth
label="Alternate Email Address"
label="Alternate Email Addresses (comma separated)"
name="otherMails"
formControl={formControl}
validators={{ validate: (value) => !value || getCippValidator(value, "email") }}
validators={{ validate: validateOtherMails }}
/>
</Grid>
{userSettingsDefaults?.userAttributes
Expand Down
5 changes: 5 additions & 0 deletions src/layouts/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
116 changes: 116 additions & 0 deletions src/pages/email/reports/mailbox-forwarding/index.js
Original file line number Diff line number Diff line change
@@ -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 = [
<Stack direction="row" spacing={2} alignItems="center" key="actions-stack">
<CippQueueTracker
queueId={syncQueueId}
queryKey={`mailbox-forwarding-${currentTenant}`}
title="Mailbox Forwarding Sync"
/>
<Tooltip title="This report displays cached mailbox data from the CIPP reporting database. Cache timestamps are shown in the table. Click the Sync button to update the mailbox cache for the current tenant.">
<IconButton size="small">
<Info fontSize="small" />
</IconButton>
</Tooltip>
<Button
startIcon={
<SvgIcon fontSize="small">
<Sync />
</SvgIcon>
}
size="xs"
onClick={syncDialog.handleOpen}
disabled={isAllTenants}
>
Sync
</Button>
</Stack>,
];

return (
<>
{currentTenant && currentTenant !== "" ? (
<CippTablePage
title="Mailbox Forwarding Report"
apiUrl="/api/ListMailboxForwarding"
queryKey={`mailbox-forwarding-${currentTenant}`}
apiData={apiData}
simpleColumns={columns}
filters={filters}
cardButton={pageActions}
offCanvas={null}
/>
) : (
<Alert severity="warning">Please select a tenant to view mailbox forwarding settings.</Alert>
)}
<CippApiDialog
createDialog={syncDialog}
title="Sync Mailbox Cache"
fields={[]}
api={{
type: "GET",
url: "/api/ExecCIPPDBCache",
confirmText: `Run mailbox cache sync for ${currentTenant}? This will update mailbox data including forwarding settings.`,
relatedQueryKeys: [`mailbox-forwarding-${currentTenant}`],
data: {
Name: "Mailboxes",
Types: "",
},
onSuccess: (result) => {
if (result?.Metadata?.QueueId) {
setSyncQueueId(result.Metadata.QueueId);
}
},
}}
/>
</>
);
};

Page.getLayout = (page) => <DashboardLayout>{page}</DashboardLayout>;

export default Page;
3 changes: 2 additions & 1 deletion src/pages/identity/administration/users/add.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -54,6 +54,7 @@ const Page = () => {
title="User"
backButtonTitle="User Overview"
postUrl="/api/AddUser"
relatedQueryKeys={`Users - ${tenantDomain}`}
>
<Box sx={{ my: 2 }}>
<CippAddEditUser formControl={formControl} userSettingsDefaults={userSettingsDefaults} />
Expand Down