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
17 changes: 12 additions & 5 deletions src/api/ApiCall.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function ApiGetCall(props) {
title: `${
error.config?.params?.tenantFilter ? error.config?.params?.tenantFilter : ""
} Error`,
})
}),
);
}
return returnRetry;
Expand Down Expand Up @@ -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
Expand All @@ -220,7 +220,7 @@ export function ApiPostCall({ relatedQueryKeys, onResult }) {
queryKey: query.queryKey,
queryKeyStr,
matchedPattern: wildcardPatterns.find((pattern) =>
queryKeyStr.startsWith(pattern)
queryKeyStr.startsWith(pattern),
),
});
}
Expand Down Expand Up @@ -252,15 +252,22 @@ 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;
if (failureCount >= MAX_RETRIES) {
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;
}

Expand All @@ -270,7 +277,7 @@ export function ApiGetCallWithPagination({
message: getCippError(error),
title: "Error",
toastError: error,
})
}),
);
}
return returnRetry;
Expand Down
5 changes: 5 additions & 0 deletions src/layouts/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 6 additions & 6 deletions src/pages/cipp/logs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: <EyeIcon />,
color: "primary",
},
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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()
: ""}
</>
Expand Down
15 changes: 8 additions & 7 deletions src/pages/cipp/logs/logentry.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
/>
Expand Down
117 changes: 117 additions & 0 deletions src/pages/email/reports/calendar-permissions/index.js
Original file line number Diff line number Diff line change
@@ -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 = [
<Stack direction="row" spacing={2} alignItems="center" key="actions-stack">
<Tooltip title="This report displays cached data from the CIPP reporting database. Cache timestamps are shown in the table. Click the Sync button to update the 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>
<FormControlLabel
key="byUser"
control={
<Switch checked={byUser} onChange={(e) => setByUser(e.target.checked)} color="primary" />
}
label="Group by User"
labelPlacement="start"
/>
</Stack>,
];

return (
<>
{currentTenant && currentTenant !== "" ? (
<CippTablePage
key={`calendar-permissions-${byUser}`}
title="Calendar Permissions Report"
apiUrl="/api/ListCalendarPermissions"
queryKey={["calendar-permissions", currentTenant, byUser]}
apiData={apiData}
simpleColumns={columns}
cardButton={pageActions}
offCanvas={null}
/>
) : (
<Alert severity="warning">Please select a tenant to view calendar permissions.</Alert>
)}
<CippApiDialog
createDialog={syncDialog}
title="Sync Calendar Permissions Cache"
fields={[]}
api={{
type: "GET",
url: "/api/ExecCIPPDBCache",
confirmText: `Run calendar permissions cache sync for ${currentTenant}? This will update mailbox and calendar permission data immediately.`,
relatedQueryKeys: ["calendar-permissions"],
data: {
Name: "Calendars",
},
}}
/>
</>
);
};

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

export default Page;
Loading