Skip to content

Commit 2a8c87f

Browse files
authored
Merge pull request #3427 from JohnDuprey/dev
bugfixes and improvements
2 parents 455f49d + 808ab17 commit 2a8c87f

File tree

5 files changed

+168
-41
lines changed

5 files changed

+168
-41
lines changed

src/components/CippCards/CippDomainCards.jsx

Lines changed: 136 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
Typography,
1111
Chip,
1212
Stack,
13+
Divider,
14+
FormControlLabel,
1315
} from "@mui/material";
1416
import SearchIcon from "@mui/icons-material/Search";
1517
import ClearIcon from "@mui/icons-material/Clear";
@@ -19,7 +21,7 @@ import ErrorIcon from "@mui/icons-material/Error";
1921
import WarningIcon from "@mui/icons-material/Warning";
2022
import HelpIcon from "@mui/icons-material/Help";
2123
import MoreVertIcon from "@mui/icons-material/MoreVert";
22-
import { Controller, get, useForm } from "react-hook-form";
24+
import { Controller, useForm } from "react-hook-form";
2325
import { ApiGetCall } from "/src/api/ApiCall";
2426
import CippButtonCard from "/src/components/CippCards/CippButtonCard";
2527
import { CippCodeBlock } from "/src/components/CippComponents/CippCodeBlock";
@@ -268,6 +270,60 @@ function DomainResultCard({ title, data, isFetching, info, type }) {
268270
</>
269271
),
270272
}
273+
: type === "HTTPS"
274+
? {
275+
children: (
276+
<>
277+
{data?.Tests?.map((test, index) => (
278+
<>
279+
<CippPropertyListCard
280+
key={index}
281+
title={`Certificate info for ${test.Hostname}`}
282+
copyItems={true}
283+
showDivider={false}
284+
propertyItems={[
285+
{
286+
label: "Issuer",
287+
value:
288+
test.Certificate.Issuer.match(/O=([^,]+)/)?.[1] ||
289+
test.Certificate.Issuer,
290+
},
291+
{
292+
label: "Subject",
293+
value:
294+
test.Certificate.Subject.match(/CN=([^,]+)/)?.[1] ||
295+
test.Certificate.Subject,
296+
},
297+
{
298+
label: "Created",
299+
value: getCippFormatting(test.Certificate.NotBefore, "NotBefore"),
300+
},
301+
{
302+
label: "Expires",
303+
value: getCippFormatting(test.Certificate.NotAfter, "NotAfter"),
304+
},
305+
{ label: "Serial Number", value: test.Certificate.SerialNumber },
306+
{ label: "Thumbprint", value: test.Certificate.Thumbprint },
307+
{
308+
label: "DNS Names",
309+
value: getCippFormatting(
310+
test.Certificate.DnsNameList.map((dns) => dns.Unicode),
311+
"DNSName"
312+
),
313+
},
314+
]}
315+
/>
316+
<ResultList
317+
passes={test.ValidationPasses}
318+
warns={test.ValidationWarns}
319+
fails={test.ValidationFails}
320+
/>
321+
<Divider />
322+
</>
323+
))}
324+
</>
325+
),
326+
}
271327
: {};
272328

273329
return (
@@ -326,6 +382,9 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
326382
});
327383
const [optionsVisible, setOptionsVisible] = useState(false);
328384
const [domain, setDomain] = useState(propDomain);
385+
const [selector, setSelector] = useState("");
386+
const [spfRecord, setSpfRecord] = useState("");
387+
const [subdomains, setSubdomains] = useState("");
329388
const enableHttps = watch("enableHttps");
330389

331390
useEffect(() => {
@@ -337,13 +396,20 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
337396

338397
const onSubmit = (values) => {
339398
setDomain(values.domain);
399+
setSelector(values.dkimSelector);
400+
setSpfRecord(values.spfRecord);
401+
setSubdomains(values.subdomains);
340402
};
341403

342404
const handleClear = () => {
343405
setValue("domain", "");
344406
setValue("spfRecord", "");
345407
setValue("dkimSelector", "");
346408
setValue("subdomains", "");
409+
setDomain("");
410+
setSelector("");
411+
setSpfRecord("");
412+
setSubdomains("");
347413
};
348414

349415
// API calls with dynamic queryKey using domain
@@ -370,8 +436,8 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
370436

371437
const { data: spfData, isFetching: spfLoading } = ApiGetCall({
372438
url: "/api/ListDomainHealth",
373-
queryKey: `spf-${domain}`,
374-
data: { Domain: domain, Action: "ReadSPFRecord" },
439+
queryKey: `spf-${domain}-${spfRecord}`,
440+
data: { Domain: domain, Action: "ReadSPFRecord", Record: spfRecord },
375441
waiting: !!domain,
376442
});
377443

@@ -384,8 +450,8 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
384450

385451
const { data: dkimData, isFetching: dkimLoading } = ApiGetCall({
386452
url: "/api/ListDomainHealth",
387-
queryKey: `dkim-${domain}`,
388-
data: { Domain: domain, Action: "ReadDkimRecord" },
453+
queryKey: `dkim-${domain}-${selector}`,
454+
data: { Domain: domain, Action: "ReadDkimRecord", Selector: selector },
389455
waiting: !!domain,
390456
});
391457

@@ -403,6 +469,13 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
403469
waiting: !!domain,
404470
});
405471

472+
const { data: httpsData, isFetching: httpsLoading } = ApiGetCall({
473+
url: "/api/ListDomainHealth",
474+
queryKey: `https-${domain}-${subdomains}`,
475+
data: { Domain: domain, Action: "TestHttpsCertificate", Subdomains: subdomains },
476+
waiting: !!domain && enableHttps,
477+
});
478+
406479
// Adjust grid item size based on fullwidth prop
407480
const gridItemSize = fullwidth ? 12 : 4;
408481

@@ -438,45 +511,50 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
438511
</Grid>
439512
</Grid>
440513
<Collapse in={optionsVisible}>
441-
<Controller
442-
name="spfRecord"
443-
control={control}
444-
render={({ field }) => (
445-
<TextField {...field} fullWidth label="SPF Record" className="mt-2" />
446-
)}
447-
/>
448-
<Controller
449-
name="dkimSelector"
450-
control={control}
451-
render={({ field }) => (
452-
<TextField {...field} fullWidth label="DKIM Selector" className="mt-2" />
453-
)}
454-
/>
455-
<Controller
456-
name="enableHttps"
457-
control={control}
458-
render={({ field }) => (
459-
<Switch {...field} checked={field.value} label="Enable HTTPS check" />
460-
)}
461-
/>
462-
{enableHttps && (
514+
<Stack direction="column" spacing={1} sx={{ mt: 1 }}>
463515
<Controller
464-
name="subdomains"
516+
name="spfRecord"
465517
control={control}
466518
render={({ field }) => (
467-
<TextField {...field} fullWidth label="HTTPS Subdomains" className="mt-2" />
519+
<TextField {...field} fullWidth label="SPF Record" className="mt-2" />
468520
)}
469521
/>
470-
)}
471-
<Button
472-
variant="outlined"
473-
color="error"
474-
startIcon={<ClearIcon />}
475-
onClick={handleClear}
476-
className="mt-2"
477-
>
478-
Clear
479-
</Button>
522+
<Controller
523+
name="dkimSelector"
524+
control={control}
525+
render={({ field }) => (
526+
<TextField {...field} fullWidth label="DKIM Selector" className="mt-2" />
527+
)}
528+
/>
529+
<Controller
530+
name="enableHttps"
531+
control={control}
532+
render={({ field }) => (
533+
<FormControlLabel
534+
control={<Switch {...field} checked={field.value} />}
535+
label="Enable HTTPS check"
536+
/>
537+
)}
538+
/>
539+
{enableHttps && (
540+
<Controller
541+
name="subdomains"
542+
control={control}
543+
render={({ field }) => (
544+
<TextField {...field} fullWidth label="HTTPS Subdomains" className="mt-2" />
545+
)}
546+
/>
547+
)}
548+
<Button
549+
variant="outlined"
550+
color="error"
551+
startIcon={<ClearIcon />}
552+
onClick={handleClear}
553+
className="mt-2"
554+
>
555+
Clear
556+
</Button>
557+
</Stack>
480558
</Collapse>
481559
</CippButtonCard>
482560
</Grid>
@@ -605,6 +683,25 @@ export const CippDomainCards = ({ domain: propDomain = "", fullwidth = false })
605683
}
606684
/>
607685
</Grid>
686+
{enableHttps && (
687+
<Grid item xs={12} md={gridItemSize}>
688+
<DomainResultCard
689+
title="HTTPS Certificate"
690+
type="HTTPS"
691+
data={httpsData}
692+
isFetching={httpsLoading}
693+
info={
694+
<div>
695+
<ResultList
696+
passes={httpsData?.ValidationPasses}
697+
warns={httpsData?.ValidationWarns}
698+
fails={httpsData?.ValidationFails}
699+
/>
700+
</div>
701+
}
702+
/>
703+
</Grid>
704+
)}
608705
</>
609706
)}
610707
</Grid>

src/components/CippCards/CippPropertyListCard.jsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ export const CippPropertyListCard = (props) => {
4444
};
4545

4646
const setPadding = isLabelPresent ? { py: 0.5, px: 3 } : { py: 1.5, px: 3 };
47+
const handleActionDisabled = (row, action) => {
48+
if (action?.condition) {
49+
return !action.condition(row);
50+
}
51+
return false;
52+
};
4753

4854
return (
4955
<>
@@ -133,7 +139,7 @@ export const CippPropertyListCard = (props) => {
133139
{actionItems?.length > 0 &&
134140
actionItems.map((item, index) => (
135141
<ActionListItem
136-
key={`${item.label}-index-ActionList-OffCanvas`}
142+
key={`${item.label}-${index}-ActionList-OffCanvas`}
137143
icon={<SvgIcon fontSize="small">{item.icon}</SvgIcon>}
138144
label={item.label}
139145
onClick={
@@ -148,6 +154,7 @@ export const CippPropertyListCard = (props) => {
148154
createDialog.handleOpen();
149155
}
150156
}
157+
disabled={handleActionDisabled(data, item)}
151158
/>
152159
))}
153160
</ActionList>

src/components/CippTable/CippDataTable.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ export const CippDataTable = (props) => {
156156
const memoizedColumns = useMemo(() => usedColumns, [usedColumns]);
157157
const memoizedData = useMemo(() => usedData, [usedData]);
158158

159+
const handleActionDisabled = (row, action) => {
160+
if (action?.condition) {
161+
return !action.condition(row);
162+
}
163+
return false;
164+
};
165+
159166
const table = useMaterialReactTable({
160167
mrtTheme: (theme) => ({
161168
baseBackgroundColor: theme.palette.background.paper,
@@ -173,7 +180,6 @@ export const CippDataTable = (props) => {
173180
) : undefined,
174181
onColumnVisibilityChange: setColumnVisibility,
175182
...modeInfo,
176-
177183
renderRowActionMenuItems: actions
178184
? ({ closeMenu, row }) => [
179185
actions.map((action, index) => (
@@ -195,6 +201,7 @@ export const CippDataTable = (props) => {
195201
closeMenu();
196202
}
197203
}}
204+
disabled={handleActionDisabled(row.original, action)}
198205
>
199206
<SvgIcon fontSize="small" sx={{ minWidth: "30px" }}>
200207
{action.icon}

src/pages/email/administration/mailboxes/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Layout as DashboardLayout } from "/src/layouts/index.js";
22
import { CippTablePage } from "/src/components/CippComponents/CippTablePage.jsx";
33
import Link from "next/link";
44
import { Button } from "@mui/material";
5+
import { Row } from "jspdf-autotable";
56

67
const Page = () => {
78
const pageTitle = "Mailboxes";
@@ -35,6 +36,18 @@ const Page = () => {
3536
ID: "UPN",
3637
},
3738
confirmText: "Are you sure you want to convert this mailbox to a shared mailbox?",
39+
condition: (row) => row.recipientTypeDetails !== "SharedMailbox",
40+
},
41+
{
42+
label: "Convert to User Mailbox",
43+
type: "GET",
44+
url: "/api/ExecConvertToSharedMailbox",
45+
data: {
46+
ID: "UPN",
47+
ConvertToUser: true,
48+
},
49+
confirmText: "Are you sure you want to convert this mailbox to a user mailbox?",
50+
condition: (row) => row.recipientTypeDetails !== "UserMailbox",
3851
},
3952
{
4053
label: "Convert to Room Mailbox",
@@ -44,6 +57,7 @@ const Page = () => {
4457
ID: "UPN",
4558
},
4659
confirmText: "Are you sure you want to convert this mailbox to a room mailbox?",
60+
condition: (row) => row.recipientTypeDetails !== "RoomMailbox",
4761
},
4862
{
4963
label: "Hide from Global Address List",

src/utils/get-cipp-formatting.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ export const getCippFormatting = (data, cellName, type, canReceive) => {
108108
"purchaseDate",
109109
"NextOccurrence",
110110
"LastOccurrence",
111+
"NotBefore",
112+
"NotAfter",
111113
];
112114

113115
const matchDateTime = /[dD]ate[tT]ime/;

0 commit comments

Comments
 (0)