mirror of
https://github.com/Lissy93/web-check.git
synced 2024-11-23 00:34:21 +01:00
🦄 Came back to this project after a year.... implemented lots of things
This commit is contained in:
parent
a6043d51d4
commit
920ab64410
@ -8,7 +8,6 @@ export const Card = styled.section`
|
|||||||
box-shadow: 4px 4px 0px ${colors.bgShadowColor};
|
box-shadow: 4px 4px 0px ${colors.bgShadowColor};
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
margin: 1rem;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// interface CardProps {
|
// interface CardProps {
|
||||||
|
69
src/components/Results/BuiltWith.tsx
Normal file
69
src/components/Results/BuiltWith.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { TechnologyGroup, Technology } from 'utils/result-processor';
|
||||||
|
import colors from 'styles/colors';
|
||||||
|
import Card from 'components/Form/Card';
|
||||||
|
import Heading from 'components/Form/Heading';
|
||||||
|
|
||||||
|
const Outer = styled(Card)`
|
||||||
|
grid-row: span 2
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Row = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.25rem;
|
||||||
|
&:not(:last-child) { border-bottom: 1px solid ${colors.primary}; }
|
||||||
|
span.lbl { font-weight: bold; }
|
||||||
|
span.val {
|
||||||
|
max-width: 200px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DataRow = (props: { lbl: string, val: string }) => {
|
||||||
|
const { lbl, val } = props;
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<span className="lbl">{lbl}</span>
|
||||||
|
<span className="val" title={val}>{val}</span>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListRow = (props: { list: Technology[], title: string }) => {
|
||||||
|
const { list, title } = props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading as="h3" size="small" align="left" color={colors.primary}>{title}</Heading>
|
||||||
|
{ list.map((entry: Technology, index: number) => {
|
||||||
|
return (
|
||||||
|
<Row key={`${title.toLocaleLowerCase()}-${index}`}><span>{ entry.Name }</span></Row>
|
||||||
|
)}
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BuiltWithCard = (props: { technologies: TechnologyGroup[] }): JSX.Element => {
|
||||||
|
// const { created, updated, expires, nameservers } = whois;
|
||||||
|
const { technologies } = props;
|
||||||
|
return (
|
||||||
|
<Outer>
|
||||||
|
<Heading as="h3" size="small" align="left" color={colors.primary}>Technologies</Heading>
|
||||||
|
{ technologies.map((group: TechnologyGroup) => {
|
||||||
|
return (
|
||||||
|
<ListRow key={group.tag} title={group.tag} list={group.technologies} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{/* { created && <DataRow lbl="Created" val={formatDate(created)} /> }
|
||||||
|
{ updated && <DataRow lbl="Updated" val={formatDate(updated)} /> }
|
||||||
|
{ expires && <DataRow lbl="Expires" val={formatDate(expires)} /> }
|
||||||
|
{ nameservers && <ListRow title="Name Servers" list={nameservers} /> } */}
|
||||||
|
</Outer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BuiltWithCard;
|
@ -6,7 +6,8 @@ import Card from 'components/Form/Card';
|
|||||||
import Heading from 'components/Form/Heading';
|
import Heading from 'components/Form/Heading';
|
||||||
|
|
||||||
const Outer = styled(Card)`
|
const Outer = styled(Card)`
|
||||||
max-width: 24rem;
|
max-height: 20rem;
|
||||||
|
overflow: auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Row = styled.div`
|
const Row = styled.div`
|
||||||
|
@ -5,9 +5,7 @@ import colors from 'styles/colors';
|
|||||||
import Card from 'components/Form/Card';
|
import Card from 'components/Form/Card';
|
||||||
import Heading from 'components/Form/Heading';
|
import Heading from 'components/Form/Heading';
|
||||||
|
|
||||||
const Outer = styled(Card)`
|
const Outer = styled(Card)``;
|
||||||
max-width: 24rem;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Row = styled.div`
|
const Row = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -34,7 +32,7 @@ const DataRow = (props: { lbl: string, val: string }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ServerInfoCard = (info: ServerInfo): JSX.Element => {
|
const ServerInfoCard = (info: ServerInfo): JSX.Element => {
|
||||||
const { org, asn, isp, os } = info;
|
const { org, asn, isp, os, ports } = info;
|
||||||
return (
|
return (
|
||||||
<Outer>
|
<Outer>
|
||||||
<Heading as="h3" size="small" align="left" color={colors.primary}>Server Info</Heading>
|
<Heading as="h3" size="small" align="left" color={colors.primary}>Server Info</Heading>
|
||||||
@ -42,6 +40,7 @@ const ServerInfoCard = (info: ServerInfo): JSX.Element => {
|
|||||||
{ (isp && isp !== org) && <DataRow lbl="Service Provider" val={isp} /> }
|
{ (isp && isp !== org) && <DataRow lbl="Service Provider" val={isp} /> }
|
||||||
{ os && <DataRow lbl="Operating System" val={os} /> }
|
{ os && <DataRow lbl="Operating System" val={os} /> }
|
||||||
{ asn && <DataRow lbl="ASN Code" val={asn} /> }
|
{ asn && <DataRow lbl="ASN Code" val={asn} /> }
|
||||||
|
{ ports && <DataRow lbl="Ports" val={ports} /> }
|
||||||
</Outer>
|
</Outer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import Flag from 'components/misc/Flag';
|
|||||||
import { TextSizes } from 'styles/typography';
|
import { TextSizes } from 'styles/typography';
|
||||||
|
|
||||||
const Outer = styled(Card)`
|
const Outer = styled(Card)`
|
||||||
max-width: 24rem;
|
grid-row: span 2
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Row = styled.div`
|
const Row = styled.div`
|
||||||
|
71
src/components/Results/WhoIs.tsx
Normal file
71
src/components/Results/WhoIs.tsx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Whois } from 'utils/result-processor';
|
||||||
|
import colors from 'styles/colors';
|
||||||
|
import Card from 'components/Form/Card';
|
||||||
|
import Heading from 'components/Form/Heading';
|
||||||
|
|
||||||
|
const Outer = styled(Card)``;
|
||||||
|
|
||||||
|
const Row = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0.25rem;
|
||||||
|
&:not(:last-child) { border-bottom: 1px solid ${colors.primary}; }
|
||||||
|
span.lbl { font-weight: bold; }
|
||||||
|
span.val {
|
||||||
|
max-width: 200px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const formatDate = (dateString: string): string => {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
const formatter = new Intl.DateTimeFormat('en-GB', {
|
||||||
|
day: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric'
|
||||||
|
});
|
||||||
|
return formatter.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataRow = (props: { lbl: string, val: string }) => {
|
||||||
|
const { lbl, val } = props;
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<span className="lbl">{lbl}</span>
|
||||||
|
<span className="val" title={val}>{val}</span>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ListRow = (props: { list: string[], title: string }) => {
|
||||||
|
const { list, title } = props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading as="h3" size="small" align="left" color={colors.primary}>{title}</Heading>
|
||||||
|
{ list.map((entry: string, index: number) => {
|
||||||
|
return (
|
||||||
|
<Row key={`${title.toLocaleLowerCase()}-${index}`}><span>{ entry }</span></Row>
|
||||||
|
)}
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ServerInfoCard = (whois: Whois): JSX.Element => {
|
||||||
|
const { created, updated, expires, nameservers } = whois;
|
||||||
|
return (
|
||||||
|
<Outer>
|
||||||
|
<Heading as="h3" size="small" align="left" color={colors.primary}>Who Is Info</Heading>
|
||||||
|
{ created && <DataRow lbl="Created" val={formatDate(created)} /> }
|
||||||
|
{ updated && <DataRow lbl="Updated" val={formatDate(updated)} /> }
|
||||||
|
{ expires && <DataRow lbl="Expires" val={formatDate(expires)} /> }
|
||||||
|
{ nameservers && <ListRow title="Name Servers" list={nameservers} /> }
|
||||||
|
</Outer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServerInfoCard;
|
@ -8,6 +8,8 @@ import Card from 'components/Form/Card';
|
|||||||
import ServerLocationCard from 'components/Results/ServerLocation';
|
import ServerLocationCard from 'components/Results/ServerLocation';
|
||||||
import ServerInfoCard from 'components/Results/ServerInfo';
|
import ServerInfoCard from 'components/Results/ServerInfo';
|
||||||
import HostNamesCard from 'components/Results/HostNames';
|
import HostNamesCard from 'components/Results/HostNames';
|
||||||
|
import WhoIsCard from 'components/Results/WhoIs';
|
||||||
|
import BuiltWithCard from 'components/Results/BuiltWith';
|
||||||
import keys from 'utils/get-keys';
|
import keys from 'utils/get-keys';
|
||||||
import { determineAddressType, AddressType } from 'utils/address-type-checker';
|
import { determineAddressType, AddressType } from 'utils/address-type-checker';
|
||||||
|
|
||||||
@ -15,6 +17,8 @@ import {
|
|||||||
getLocation, ServerLocation,
|
getLocation, ServerLocation,
|
||||||
getServerInfo, ServerInfo,
|
getServerInfo, ServerInfo,
|
||||||
getHostNames, HostNames,
|
getHostNames, HostNames,
|
||||||
|
makeTechnologies, TechnologyGroup,
|
||||||
|
Whois,
|
||||||
} from 'utils/result-processor';
|
} from 'utils/result-processor';
|
||||||
|
|
||||||
const ResultsOuter = styled.div`
|
const ResultsOuter = styled.div`
|
||||||
@ -24,13 +28,19 @@ const ResultsOuter = styled.div`
|
|||||||
|
|
||||||
const ResultsContent = styled.section`
|
const ResultsContent = styled.section`
|
||||||
width: 95vw;
|
width: 95vw;
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
display: grid;
|
||||||
|
grid-auto-flow: dense;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin: auto;
|
||||||
|
width: calc(100% - 2rem);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Header = styled(Card)`
|
const Header = styled(Card)`
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.5rem 1rem;
|
||||||
@ -45,6 +55,8 @@ interface ResultsType {
|
|||||||
const Results = (): JSX.Element => {
|
const Results = (): JSX.Element => {
|
||||||
const [ results, setResults ] = useState<ResultsType>({});
|
const [ results, setResults ] = useState<ResultsType>({});
|
||||||
const [ locationResults, setLocationResults ] = useState<ServerLocation>();
|
const [ locationResults, setLocationResults ] = useState<ServerLocation>();
|
||||||
|
const [ whoIsResults, setWhoIsResults ] = useState<Whois>();
|
||||||
|
const [ technologyResults, setTechnologyResults ] = useState<TechnologyGroup[]>();
|
||||||
const [ ipAddress, setIpAddress ] = useState<undefined | string>(undefined);
|
const [ ipAddress, setIpAddress ] = useState<undefined | string>(undefined);
|
||||||
const [ addressType, setAddressType ] = useState<AddressType>('empt');
|
const [ addressType, setAddressType ] = useState<AddressType>('empt');
|
||||||
const { address } = useParams();
|
const { address } = useParams();
|
||||||
@ -62,7 +74,6 @@ const Results = (): JSX.Element => {
|
|||||||
const fetchIpAddress = () => {
|
const fetchIpAddress = () => {
|
||||||
fetch(`/find-url-ip?address=${address}`)
|
fetch(`/find-url-ip?address=${address}`)
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
console.log(response);
|
|
||||||
response.json().then(jsonData => {
|
response.json().then(jsonData => {
|
||||||
console.log('Get IP Address', jsonData);
|
console.log('Get IP Address', jsonData);
|
||||||
setIpAddress(jsonData.ip);
|
setIpAddress(jsonData.ip);
|
||||||
@ -107,6 +118,7 @@ const Results = (): JSX.Element => {
|
|||||||
fetch(`https://api.shodan.io/shodan/host/${ipAddress}?key=${apiKey}`)
|
fetch(`https://api.shodan.io/shodan/host/${ipAddress}?key=${apiKey}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
console.log(response);
|
||||||
if (!response.error) applyShodanResults(response)
|
if (!response.error) applyShodanResults(response)
|
||||||
})
|
})
|
||||||
.catch(err => console.error(err));
|
.catch(err => console.error(err));
|
||||||
@ -117,11 +129,29 @@ const Results = (): JSX.Element => {
|
|||||||
fetchShodanData();
|
fetchShodanData();
|
||||||
}
|
}
|
||||||
}, [ipAddress]);
|
}, [ipAddress]);
|
||||||
|
|
||||||
|
/* Get BuiltWith tech stack */
|
||||||
|
useEffect(() => {
|
||||||
|
const apiKey = keys.builtWith;
|
||||||
|
const endpoint = `https://api.builtwith.com/v21/api.json?KEY=${apiKey}&LOOKUP=${address}`;
|
||||||
|
fetch(endpoint)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(response => {
|
||||||
|
console.log(response);
|
||||||
|
setTechnologyResults(makeTechnologies(response));
|
||||||
|
});
|
||||||
|
}, [address]);
|
||||||
|
|
||||||
/* Get WhoIs info for a given domain name */
|
/* Get WhoIs info for a given domain name */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const applyWhoIsResults = (response: any) => {
|
const applyWhoIsResults = (response: any) => {
|
||||||
console.log('WhoIs Response', response);
|
const whoIsResults: Whois = {
|
||||||
|
created: response.date_created,
|
||||||
|
expires: response.date_expires,
|
||||||
|
updated: response.date_updated,
|
||||||
|
nameservers: response.nameservers,
|
||||||
|
};
|
||||||
|
setWhoIsResults(whoIsResults);
|
||||||
}
|
}
|
||||||
const fetchWhoIsData = () => {
|
const fetchWhoIsData = () => {
|
||||||
const apiKey = keys.whoApi;
|
const apiKey = keys.whoApi;
|
||||||
@ -148,6 +178,8 @@ const Results = (): JSX.Element => {
|
|||||||
{ locationResults && <ServerLocationCard {...locationResults} />}
|
{ locationResults && <ServerLocationCard {...locationResults} />}
|
||||||
{ results.serverInfo && <ServerInfoCard {...results.serverInfo} />}
|
{ results.serverInfo && <ServerInfoCard {...results.serverInfo} />}
|
||||||
{ results.hostNames && <HostNamesCard hosts={results.hostNames} />}
|
{ results.hostNames && <HostNamesCard hosts={results.hostNames} />}
|
||||||
|
{ whoIsResults && <WhoIsCard {...whoIsResults} />}
|
||||||
|
{ technologyResults && <BuiltWithCard technologies={technologyResults} />}
|
||||||
</ResultsContent>
|
</ResultsContent>
|
||||||
</ResultsOuter>
|
</ResultsOuter>
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
const keys = {
|
const keys = {
|
||||||
shodan: process.env.SHODAN_API_KEY,
|
shodan: process.env.REACT_APP_SHODAN_API_KEY,
|
||||||
whoApi: process.env.WHO_API_KEY,
|
whoApi: process.env.REACT_APP_WHO_API_KEY,
|
||||||
|
builtWith: process.env.REACT_APP_BUILT_WITH_API_KEY,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default keys;
|
export default keys;
|
||||||
|
@ -19,6 +19,13 @@ export interface ServerLocation {
|
|||||||
countryPopulation: number,
|
countryPopulation: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface Whois {
|
||||||
|
created: string,
|
||||||
|
expires: string,
|
||||||
|
updated: string,
|
||||||
|
nameservers: string[],
|
||||||
|
}
|
||||||
|
|
||||||
export const getLocation = (response: any): ServerLocation => {
|
export const getLocation = (response: any): ServerLocation => {
|
||||||
return {
|
return {
|
||||||
city: response.city,
|
city: response.city,
|
||||||
@ -48,6 +55,8 @@ export interface ServerInfo {
|
|||||||
asn: string,
|
asn: string,
|
||||||
isp: string,
|
isp: string,
|
||||||
os?: string,
|
os?: string,
|
||||||
|
ip?: string,
|
||||||
|
ports?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getServerInfo = (response: any): ServerInfo => {
|
export const getServerInfo = (response: any): ServerInfo => {
|
||||||
@ -56,6 +65,8 @@ export const getServerInfo = (response: any): ServerInfo => {
|
|||||||
asn: response.asn,
|
asn: response.asn,
|
||||||
isp: response.isp,
|
isp: response.isp,
|
||||||
os: response.os,
|
os: response.os,
|
||||||
|
ip: response.ip_str,
|
||||||
|
ports: response.ports.toString(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,17 +78,37 @@ export interface HostNames {
|
|||||||
export const getHostNames = (response: any): HostNames => {
|
export const getHostNames = (response: any): HostNames => {
|
||||||
const { hostnames, domains } = response;
|
const { hostnames, domains } = response;
|
||||||
const results: HostNames = {
|
const results: HostNames = {
|
||||||
domains: [],
|
domains: domains || [],
|
||||||
hostnames: [],
|
hostnames: hostnames || [],
|
||||||
};
|
};
|
||||||
if (!hostnames || !domains) return results;
|
|
||||||
hostnames.forEach((host: string) => {
|
|
||||||
if (domains.includes(host)) {
|
|
||||||
results.domains.push(host);
|
|
||||||
} else {
|
|
||||||
results.hostnames.push(host);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface Technology {
|
||||||
|
Categories?: string[];
|
||||||
|
Parent?: string;
|
||||||
|
Name: string;
|
||||||
|
Description: string;
|
||||||
|
Link: string;
|
||||||
|
Tag: string;
|
||||||
|
FirstDetected: number;
|
||||||
|
LastDetected: number;
|
||||||
|
IsPremium: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TechnologyGroup {
|
||||||
|
tag: string;
|
||||||
|
technologies: Technology[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeTechnologies = (response: any): TechnologyGroup[] => {
|
||||||
|
let flatArray = response.Results[0].Result.Paths
|
||||||
|
.reduce((accumulator: any, obj: any) => accumulator.concat(obj.Technologies), []);
|
||||||
|
let technologies = flatArray.reduce((groups: any, item: any) => {
|
||||||
|
let tag = item.Tag;
|
||||||
|
if (!groups[tag]) groups[tag] = [];
|
||||||
|
groups[tag].push(item);
|
||||||
|
return groups;
|
||||||
|
}, {});
|
||||||
|
return technologies;
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user