hooks#useDomainApi TypeScript Examples
The following examples show how to use
hooks#useDomainApi.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Domains.tsx From crossfeed with Creative Commons Zero v1.0 Universal | 5 votes |
Domains: React.FC = () => {
const { showAllOrganizations } = useAuthContext();
const tableRef = useRef<TableInstance<Domain>>(null);
const columns = useMemo(() => createColumns(), []);
const [domains, setDomains] = useState<Domain[]>([]);
const [totalResults, setTotalResults] = useState(0);
const { listDomains } = useDomainApi(showAllOrganizations);
const fetchDomains = useCallback(
async (q: Query<Domain>) => {
try {
const { domains, count } = await listDomains(q);
setDomains(domains);
setTotalResults(count);
} catch (e) {
console.error(e);
}
},
[listDomains]
);
const fetchDomainsExport = async (): Promise<string> => {
const { sortBy, filters } = tableRef.current?.state ?? {};
try {
const { url } = await listDomains(
{
sort: sortBy ?? [],
page: 1,
pageSize: -1,
filters: filters ?? []
},
true
);
return url!;
} catch (e) {
console.error(e);
return '';
}
};
const renderPagination = (table: TableInstance<Domain>) => (
<Paginator
table={table}
totalResults={totalResults}
export={{
name: 'domains',
getDataToExport: fetchDomainsExport
}}
/>
);
return (
<div className={classes.root}>
<Subnav
items={[
{ title: 'Search Results', path: '/inventory', exact: true },
{ title: 'All Domains', path: '/inventory/domains' },
{ title: 'All Vulnerabilities', path: '/inventory/vulnerabilities' }
]}
></Subnav>
<br></br>
<Table<Domain>
renderPagination={renderPagination}
tableRef={tableRef}
columns={columns}
data={domains}
pageCount={Math.ceil(totalResults / PAGE_SIZE)}
fetchData={fetchDomains}
pageSize={PAGE_SIZE}
/>
</div>
);
}
Example #2
Source File: DomainDetails.tsx From crossfeed with Creative Commons Zero v1.0 Universal | 4 votes |
DomainDetails: React.FC<Props> = (props) => {
const { domainId } = props;
const { getDomain } = useDomainApi(false);
const { user } = useAuthContext();
const [domain, setDomain] = useState<Domain>();
const classes = useStyles();
const history = useHistory();
const fetchDomain = useCallback(async () => {
try {
setDomain(undefined);
const result = await getDomain(domainId);
setDomain(result);
} catch (e) {
console.error(e);
}
}, [domainId, getDomain]);
useEffect(() => {
fetchDomain();
}, [fetchDomain]);
const webInfo = useMemo(() => {
if (!domain) {
return [];
}
const categoriesToProducts: Record<string, Set<string>> = {};
for (const service of domain.services) {
for (const product of service.products) {
const version = product.version ? ` ${product.version}` : '';
const value = product.name + version;
const name =
product.tags && product.tags.length > 0 ? product.tags[0] : 'Misc';
if (!categoriesToProducts[name]) {
categoriesToProducts[name] = new Set();
}
categoriesToProducts[name].add(value);
}
}
return Object.entries(categoriesToProducts).reduce(
(acc, [name, value]) => [
...acc,
{
label: name,
value: Array.from(value).join(', ')
}
],
[] as any
);
}, [domain]);
const overviewInfo = useMemo(() => {
if (!domain) {
return [];
}
const ret = [];
if (domain.ip) {
ret.push({
label: 'IP',
value: domain.ip
});
}
ret.push({
label: 'First Seen',
value: `${differenceInCalendarDays(
Date.now(),
parseISO(domain.createdAt)
)} days ago`
});
ret.push({
label: 'Last Seen',
value: `${differenceInCalendarDays(
Date.now(),
parseISO(domain.updatedAt)
)} days ago`
});
if (domain.country) {
ret.push({
label: 'Country',
value: domain.country
});
}
if (domain.cloudHosted) {
ret.push({
label: 'Cloud Hosted',
value: 'Yes'
});
}
ret.push({
label: 'Organization',
value: domain.organization.name
});
return ret;
}, [domain]);
const [hiddenRows, setHiddenRows] = React.useState<{
[key: string]: boolean;
}>({});
const formatBytes = (bytes: number, decimals = 2): string => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
};
const generateWebpageList = (tree: any, prefix = '') => {
return (
<List
className={`${classes.listRoot}${prefix ? ' ' + classes.nested : ''}`}
>
{Object.keys(tree).map((key) => {
const isWebpage =
'url' in tree[key] && typeof tree[key]['url'] === 'string';
if (!isWebpage) {
const newPrefix = prefix + '/' + key;
return (
<>
<ListItem
button
onClick={() => {
setHiddenRows((hiddenRows: any) => {
hiddenRows[newPrefix] =
newPrefix in hiddenRows ? !hiddenRows[newPrefix] : true;
return { ...hiddenRows };
});
}}
key={newPrefix}
>
<ListItemText primary={(prefix ? '' : '/') + key + '/'} />
{hiddenRows[newPrefix] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse
in={!hiddenRows[newPrefix]}
timeout="auto"
unmountOnExit
>
{generateWebpageList(tree[key], newPrefix)}
</Collapse>
</>
);
}
const page = tree[key] as Webpage;
const parsed = new URL(page.url);
const split = parsed.pathname
.replace(/\/$/, '') // Remove trailing slash
.split('/');
return (
<ListItem
button
divider={true}
key={page.url}
onClick={() => window.open(page.url, '_blank')}
>
<ListItemText
primary={(prefix ? '' : '/') + split.pop()}
secondary={
page.status + ' • ' + formatBytes(page.responseSize ?? 0, 1)
}
></ListItemText>
</ListItem>
);
})}
</List>
);
};
if (!domain) {
return null;
}
const url =
(domain.services.find((service) => service.port === 443)
? 'https://'
: 'http://') + domain.name;
const { webpages = [] } = domain;
webpages.sort((a, b) => (a.url > b.url ? 1 : -1));
const webpageTree = generateWebpageTree(webpages);
const webpageList = generateWebpageList(webpageTree);
return (
<Paper classes={{ root: classes.root }}>
<div className={classes.title}>
<h4>
<Link to={`/inventory/domain/${domain.id}`}>{domain.name}</Link>
</h4>
<a href={url} target="_blank" rel="noopener noreferrer">
<LinkOffIcon />
</a>
</div>
<div className={classes.inner}>
{overviewInfo.length > 0 && (
<div className={classes.section}>
<h4 className={classes.subtitle}>Overview</h4>
<DefinitionList items={overviewInfo} />
</div>
)}
{webInfo.length > 0 && (
<div className={classes.section}>
<h4 className={classes.subtitle}>Known Products</h4>
<DefinitionList items={webInfo} />
</div>
)}
{domain.vulnerabilities.length > 0 && (
<div className={classes.section}>
<h4 className={classes.subtitle}>Vulnerabilities</h4>
<Accordion className={classes.accordionHeaderRow} disabled>
<AccordionSummary>
<Typography className={classes.accordionHeading}>
Title
</Typography>
<Typography className={classes.vulnDescription}>
Serverity
</Typography>
<Typography className={classes.vulnDescription}>
State
</Typography>
<Typography className={classes.vulnDescription}>
Created
</Typography>
</AccordionSummary>
</Accordion>
{domain.vulnerabilities.map((vuln) => (
<Accordion
className={classes.accordion}
key={vuln.id}
onClick={(event) => {
event.stopPropagation();
history.push('/inventory/vulnerability/' + vuln.id);
}}
>
<AccordionSummary>
<Typography className={classes.accordionHeading}>
{vuln.title}
</Typography>
<Typography className={classes.vulnDescription}>
{vuln.severity}
</Typography>
<Typography className={classes.vulnDescription}>
{vuln.state}
</Typography>
<Typography className={classes.vulnDescription}>
{vuln.createdAt
? `${differenceInCalendarDays(
Date.now(),
parseISO(vuln.createdAt)
)} days ago`
: ''}
</Typography>
</AccordionSummary>
</Accordion>
))}
</div>
)}
{domain.services.length > 0 && (
<div className={classes.section}>
<h4 className={classes.subtitle}>Ports</h4>
<Accordion className={classes.accordionHeaderRow} disabled>
<AccordionSummary expandIcon={<ExpandMore />}>
<Typography className={classes.accordionHeading}>
Port
</Typography>
<Typography className={classes.accordionHeading}>
Products
</Typography>
<Typography className={classes.lastSeen}>Last Seen</Typography>
</AccordionSummary>
</Accordion>
{domain.services.map((service) => {
const products = service.products
.map(
(product) =>
product.name +
(product.version ? ` ${product.version}` : '')
)
.join(', ');
return (
<Accordion className={classes.accordion} key={service.id}>
<AccordionSummary expandIcon={<ExpandMore />}>
<Typography className={classes.accordionHeading}>
{service.port}
</Typography>
<Typography className={classes.accordionHeading}>
{products}
</Typography>
<Typography className={classes.lastSeen}>
{service.lastSeen
? `${differenceInCalendarDays(
Date.now(),
parseISO(service.lastSeen)
)} days ago`
: ''}
</Typography>
</AccordionSummary>
{service.products.length > 0 && (
<AccordionDetails>
<DefinitionList
items={[
{
label: 'Products',
value: products
},
{
label: 'Banner',
value:
(user?.userType === 'globalView' ||
user?.userType === 'globalAdmin') &&
service.banner
? service.banner
: 'None'
}
]}
/>
</AccordionDetails>
)}
</Accordion>
);
})}
</div>
)}
{domain.webpages?.length > 0 && (
<div className={classes.section}>
<h4 className={classes.subtitle}>Site Map</h4>
{webpageList}
</div>
)}
</div>
</Paper>
);
}