Skip to content

Commit

Permalink
feat: further implement software/hardware linking & auto creating ass…
Browse files Browse the repository at this point in the history
…ets and linking them

Resolves #31
Resolves #32
Resolves #33
  • Loading branch information
LiamTownsley committed Nov 19, 2023
1 parent f1c75a6 commit d89dfc4
Show file tree
Hide file tree
Showing 17 changed files with 228 additions and 54 deletions.
2 changes: 1 addition & 1 deletion electron/api/routes/AssetLinkRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ router.post('/', async (req: Request, res: Response) => {
console.log('request got at PSOT asset-links/')
const { hardware_id, software_id, date, created_by }: APIResponse.CreateAssetLink = req.body as APIResponse.CreateAssetLink;
const collection: Collection = db.collection(DATABASE);

console.log('post asset links', req.body);
const HardwareID = new mongo.ObjectId(hardware_id);
const SoftwareID = new mongo.ObjectId(software_id)

Expand Down
16 changes: 14 additions & 2 deletions electron/api/routes/HardwareAssetRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const mongo = require('mongodb');
const router = express.Router();

const DATABASE = "hardware";
const LINK_COLLECTION_DATABASE = "asset-links";

// @ROUTE: GET api/assets/hardware/view-all
// @DESCRIPTION: Used for viewing all Software Assets.
Expand Down Expand Up @@ -37,6 +38,9 @@ router.delete('/delete-all', async (_: Request, res: Response) => {
const collection = db.collection(DATABASE);

await collection.deleteMany({});

const _linkCollection = db.collection(LINK_COLLECTION_DATABASE);
await _linkCollection.deleteMany({});
res.send({ "status": true });
})
});
Expand All @@ -62,20 +66,26 @@ router.delete('/:id', async (req: Request, res: Response) => {
const id = req.params.id;

await collection.deleteOne({ _id: new mongo.ObjectId(id) });

const _linkCollection = db.collection(LINK_COLLECTION_DATABASE);
await _linkCollection.deleteMany({});
res.json({ "status": true });
})
});

// @ROUTE: POST api/assets/hardware
// @DESCRIPTION: Used for creating a Software Asset.
router.post('/', async (req: Request, _: Response) => {
router.post('/', async (req: Request, res: Response) => {
await wrapper(async (db: any) => {
console.log(req.body);
const collection = db.collection(DATABASE);
const { name, type, model, manufacturer, ip, date, note, parent_employee } = req.body;
const _employee = new mongo.ObjectId(parent_employee);

collection.insertOne({
const isFound = await collection.find({ name, model, manufacturer, ip }).toArray();
if(isFound.length > 0) return res.send({ status: false });

const resp = await collection.insertOne({
name,
type,
model,
Expand All @@ -85,6 +95,8 @@ router.post('/', async (req: Request, _: Response) => {
note,
parent_employee: _employee
})

return res.json({ status: true, id: resp.insertedId });
})
})

Expand Down
14 changes: 12 additions & 2 deletions electron/api/routes/SoftwareAssetRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const mongo = require('mongodb');
const router = express.Router();

const DATABASE = "software";
const LINK_COLLECTION_DATABASE = "asset-links";

// @ROUTE: GET api/assets/hardware/view-all
// @DESCRIPTION: Used for viewing all Software Assets.
Expand Down Expand Up @@ -37,6 +38,9 @@ router.delete('/delete-all', async (_: Request, res: Response) => {
const collection = db.collection(DATABASE);

await collection.deleteMany({});

const _linkCollection = db.collection(LINK_COLLECTION_DATABASE);
await _linkCollection.deleteMany({});
res.send({ "status": true });
})
});
Expand All @@ -62,6 +66,9 @@ router.delete('/:id', async (req: Request, res: Response) => {
const id = req.params.id;

await collection.deleteOne({ _id: new mongo.ObjectId(id) });

const _linkCollection = db.collection(LINK_COLLECTION_DATABASE);
await _linkCollection.deleteMany({ hardware_id: new mongo.ObjectId(id) });
res.json({ "status": true });
})
});
Expand All @@ -74,7 +81,10 @@ router.post('/', async (req: Request, res: Response) => {
const collection = db.collection(DATABASE);
const { name, manufacturer, version, risk_level } = req.body;

collection.insertOne({
const isFound = await collection.find({ name, manufacturer, version }).toArray();
if(isFound.length > 0) return res.send({ status: false });

const resp = await collection.insertOne({
name,
manufacturer,
version,
Expand All @@ -83,7 +93,7 @@ router.post('/', async (req: Request, res: Response) => {
last_edit_at: new Date().toISOString()
})

res.send({ status: true })
res.json({ status: true, id: resp.insertedId })
})
})

Expand Down
23 changes: 15 additions & 8 deletions src/components/assets/hardware/HardwareAssetInfoTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class HardwareAssetInfoTable extends Component<{ asset: HardwareAsset }, { isLoa
}

render() {
const name = (this.state.data?.forename + ' ' + this.state.data?.surname) ?? '-';

return (
<table id="single-asset-table" className="table">
<tr>
Expand All @@ -39,11 +41,11 @@ class HardwareAssetInfoTable extends Component<{ asset: HardwareAsset }, { isLoa
</tr>
<tr>
<th><i className="fa fa-list-alt" /> Model</th>
<td>{this.props.asset.model ?? '-'}</td>
<td>{(!(this.props.asset.model == "" || !this.props.asset.model)) ? this.props.asset.model : '-'}</td>
</tr>
<tr>
<th><i className="fa fa-cogs" /> Manufacturer</th>
<td>{this.props.asset.manufacturer ?? '-'}</td>
<td>{(!(this.props.asset.model == "" || !this.props.asset.model)) ? this.props.asset.manufacturer : '-'}</td>
</tr>
<tr>
<th><i className="fa fa-exchange" /> Asset Type</th>
Expand All @@ -53,17 +55,22 @@ class HardwareAssetInfoTable extends Component<{ asset: HardwareAsset }, { isLoa
<th><i className="fa fa-wifi" /> IP Address</th>
<td>{this.props.asset.ip ?? '-'}</td>
</tr>
<tr>
<th><i className="fa fa-user" /> Supervising Employee</th>
<td>{(this.state.data) ? <><Link to={`/employees/${this.state.data._id}`}>{this.state.data?.forename + ' ' + this.state.data.surname ?? '-'}</Link><code>(ID: {this.state.data?._id.toString() ?? '-'})</code></> : '-'}</td>
</tr>
{(this.state.data) ?
<tr>
<th><i className="fa fa-user" /> Supervising Employee</th>
<td><><Link to={`/employees/${this.state.data._id}`}><i className="fa fa-link" />{name}</Link><code>(ID: {this.state.data?._id.toString()})</code></></td>
</tr>
: <tr id="warning">
<th><i className="fa fa-user" /> Supervising Employee</th>
<td>-</td>
</tr>}
<tr>
<th><i className="fa fa-calendar" /> Purchase Date</th>
<td>{this.props.asset.date}</td>
<td>{(!(this.props.asset.date == "" || !this.props.asset.date) ? this.props.asset.date : '-')}</td>
</tr>
<tr>
<th><i className="fa fa-sticky-note-o" /> Note</th>
<td>{this.props.asset.note}</td>
<td>{(!(this.props.asset.date == "" || !this.props.asset.note) ? this.props.asset.note : '-')}</td>
</tr>
</table>
)
Expand Down
2 changes: 1 addition & 1 deletion src/components/assets/hardware/HardwareAssetTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class HardwareAssetTable extends Component<{ assets: HardwareAsset[] }> {
}} className="btn btn-outline-danger"><i className="fa fa-trash" /> Delete Asset</button>
</td>
</tr>
)) : <p>Loading...</p>}
)) : <p className="text-centre">Loading...</p>}
</tbody>
</table>

Expand Down
6 changes: 4 additions & 2 deletions src/components/assets/software/SoftwareAssetTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ class SoftwareAssetTable extends Component<{ assets: SoftwareAsset[] }> {
<td><PillButton label={item.risk_level} /></td>
<td>
<Link to={`/software/${item._id}`} role="button" id="blue-button" className="btn btn-outline-primary "><i className="fa fa-eye" /> View Asset</Link>
<Link to={`/software/${item._id}/edit`} role="button" id="blue-button" className="btn btn-outline-primary "><i className="fa fa-edit" /> Edit Asset</Link>
<Link to={`/software/${item._id}/edit`} role="button" id="blue-button" className="btn btn-outline-primary "><i className="fa fa-wrench" /> Edit Asset</Link>
<button onClick={() => {
fetch(`http://127.0.0.1:3001/api/assets/software/${item._id}`, { method: 'DELETE' }).then(() => {
this.refreshPage();
})
}} className="btn btn-outline-danger"><i className="fa fa-trash" /> Delete Asset</button>
<Link to={`/software/${item._id}/scan`} role="button" id="blue-button" className="btn btn-outline-secondary disabled"><i className="fa fa-dot-circle-o" /> Scan Asset</Link>
<Link to={`/software/${item._id}/scans`} role="button" id="blue-button" className="btn btn-outline-secondary disabled"><i className="fa fa-dot-circle-o" /> View Scans</Link>
{/* @TODO (NIST): Change below link to API request to start a scan. */}
<Link to={`/software/${item._id}/scan`} role="button" id="blue-button" className="btn btn-outline-secondary disabled"><i className="fa fa-wrench" /> Scan Asset</Link>
</td>
</tr>
))}
Expand Down
5 changes: 3 additions & 2 deletions src/components/assets/software/SoftwareLinkTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ class SoftwareLinkTable extends Component<{ assets: { software: SoftwareAsset, l
this.refreshPage();
})
}} className="btn btn-outline-danger"><i className="fa fa-trash" /> Delete Asset Link</button>
<Link to={`/software/${item.software._id}/scan`} role="button" id="blue-button" className="btn btn-outline-secondary disabled"><i className="fa fa-dot-circle-o" /> Scan Asset</Link>
</td>
<Link to={`/software/${item._id}/scans`} role="button" id="blue-button" className="btn btn-outline-secondary disabled"><i className="fa fa-dot-circle-o" /> View Scans</Link>
{/* @TODO (NIST): Change below link to API request to start a scan. */}
<Link to={`/software/${item._id}/scan`} role="button" id="blue-button" className="btn btn-outline-secondary disabled"><i className="fa fa-wrench" /> Scan Asset</Link> </td>
</tr>
))}
</tbody>
Expand Down
8 changes: 8 additions & 0 deletions src/interfaces/IPC.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
export interface IIPCSystemData {
cpu: string;
platform: string;
distro: string;
release: string;
manufacturer: string;
model: string;
ip: string;
hostname: string;
isLaptop: boolean;
}
69 changes: 63 additions & 6 deletions src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,87 @@ import { Link } from "react-router-dom";
import TopBar from "../components/TopBar";
import Breadcrumbs from '../components/Breadcrumbs';
import { IEmployee } from '../interfaces/Employee';
import { IIPCSystemData } from '../interfaces/IPC';

class Home extends Component<{ setUser: Function, user: IEmployee }, { user: IEmployee, setUser: Function }> {
class Home extends Component<{ setUser: Function, user: IEmployee }, { user: IEmployee, setUser: Function, data: any }> {
constructor(props: any) {
super(props);
this.state = {
user: props.user,
setUser: props.setUser
setUser: props.setUser,
data: undefined
}
console.log(this.props.user);
this.logout = this.logout.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
}

componentDidMount() {
try {
// @ts-ignore: Unreachable code error
window.electron.getData().then(async (data: IIPCSystemData) => {
console.log('mountdata->', data);
this.setState({ data: data });
console.log('SWID FETCH');
const swid = await fetch(`http://127.0.0.1:3001/api/assets/software`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: data.distro, version: data.release, manufacturer: data.platform, risk_level: 'N/A' })
})

const hwid = await fetch(`http://127.0.0.1:3001/api/assets/hardware`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: data.hostname, manufacturer: data.manufacturer, model: data.model, type: (data.isLaptop) ? 'Laptop' : 'Workstation', ip: data.ip })
})

const swid_json = await swid.json();
const hwid_json = await hwid.json();
console.log(swid_json);
console.log(hwid_json);
console.log('HWID FETCH');

const _data = {
software_id: swid_json.id,
hardware_id: hwid_json.id,
date: new Date().toISOString(),
created_by: this.props.user.email
}

console.log(_data);
console.log('ASSET LINKFETCH');
const resp = await fetch('http://127.0.0.1:3001/api/asset-link', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(_data)
}).then(res => res.json()).catch(() => { })

console.log(resp);
})
} catch (error) { }
}

render() {
return (
<>
<TopBar linkToHomepage={false} />
<Breadcrumbs history={[]} username={this.props.user.email} setUser={this.props.setUser} />
<div className='hero hero-index text-centre'>
<br />
<h2><i className='fa fa-home' /> Welcome to the <strong>ScottishGlen</strong> Administration Panel!</h2>
<br />
</div>
<div id='info-parent'>
<div id='info-child' className='text-centre'>
<br />
<h1>Welcome to the ScottishGlen Administration Panel!</h1>
<br />
<p>From here you can manage the <Link to={'/hardware'}>Hardware</Link> & <Link to={'/software'}>Software</Link> assets and use it to get a general overview of the assets contained within the company.</p>
<p>It can also be used for Vulnerability Scanning through the <a href='https://nvd.nist.gov/' target='_blank'>National Vulnerability Database</a>. If at anytime you would like to return to this page, click the logo at the top of your screen!</p>
<p>From here you can manage the <Link to={'/hardware'}><i className='fa fa-server' /> Hardware</Link> and <Link to={'/software'}><i className='fa fa-cloud-download' /> Software</Link> assets and use it to get a general overview of the assets contained within the company.</p>
<p>It can also be used for Vulnerability Scanning.<br />It does this through use of the <a href='https://nvd.nist.gov/' target='_blank'><i className='fa fa-shield' /> National Vulnerability Database</a><br /><br />If at anytime you would like to return to this page, click the logo at the top of your screen!</p>
</div>
</div>
<div className="container py-4 px-3 mx-auto button-list-container">
Expand Down
12 changes: 0 additions & 12 deletions src/pages/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Component } from "react";
import TopBar from "../components/TopBar";
import '../styles/Login.scss';
import { IEmployee } from "../interfaces/Employee";
import { IIPCSystemData } from "../interfaces/IPC";

class Login extends Component<{ setUser: Function, user: IEmployee }> {
private _setUser: any;
Expand All @@ -16,7 +15,6 @@ class Login extends Component<{ setUser: Function, user: IEmployee }> {
this._setUser = props.setUser;
this.handleFormSubmission = this.handleFormSubmission.bind(this);
this.handleFormUpdate = this.handleFormUpdate.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
}

handleFormUpdate(e: any) {
Expand Down Expand Up @@ -51,16 +49,6 @@ class Login extends Component<{ setUser: Function, user: IEmployee }> {
});
}

componentDidMount() {
try {
// @ts-ignore: Unreachable code error
window.electron.getData().then((data: IIPCSystemData) => {
console.log('mountdata->', data);
this.setState({ data: data });
})
} catch (error) { }
}

render() {
return (
<>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/assets/hardware/HardwareAsset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class HardwareAsset extends Component<{ setUser: Function, user: IEmployee, id:
<hr />
</div>
<div id="action-buttons">
<Link to={`/hardware/${this._id}/install`} className="btn btn-outline-primary"><i className="fa fa-tasks" /> Link Software</Link>
<Link to={`/hardware/${this._id}/install`} className="btn btn-outline-primary"><i className="fa fa-cloud-download" /> Link Software</Link>
<Link to={`/hardware/${this._id}/edit`} className="btn btn-outline-primary"><i className="fa fa-edit" /> Edit Asset</Link>
<button onClick={this.refreshPage} className="btn btn-outline-primary"><i className="fa fa-refresh" /> Refresh Asset</button>
<button onClick={this.delete} className="btn btn-outline-danger"><i className="fa fa-trash" /> Delete Asset</button>
Expand All @@ -80,7 +80,7 @@ class HardwareAsset extends Component<{ setUser: Function, user: IEmployee, id:
<div id="centred-div">
<HardwareAssetInfoTable asset={this.state.hardware_data} />
</div> :
<p>Loading...</p>
<p className="text-centre">Loading...</p>
}

{this.state.software_data && this.state.software_data.length > 0 ?
Expand Down
8 changes: 6 additions & 2 deletions src/pages/assets/hardware/InstallSoftware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class InstallSoftware extends Component<{ setUser: Function, user: IEmployee, na
.catch((err) => console.error(err))
}

onSubmit = (e:any) => {
onSubmit = (e: any) => {
e.preventDefault();
console.log(this.state);
//method="post" action="http://127.0.0.1:3001/api/asset-link/" onSubmit={async () => { await delay(1000); this.props.navigate('/assets')
Expand Down Expand Up @@ -71,7 +71,11 @@ class InstallSoftware extends Component<{ setUser: Function, user: IEmployee, na
{ name: this._id, path: `/hardware/${this._id}` },
{ name: 'Link Software', path: `/hardware/${this._id}/install` },
]} setUser={this.state.setUser} username={this.state.user.email} />
<h2 className="text-centre">Link a Software Asset</h2>
<div className="hero">
<div id="spacer"></div>
<h2 className="text-centre"><i className="fa fa-cloud-download" /> Link a Software Asset</h2>
<hr />
</div>

<form id="asset-form" onSubmit={this.onSubmit}>
<label><i className="fa fa-user" /> What Software Asset do you want to link this asset to? <span className="red-star">*</span></label>
Expand Down
Loading

0 comments on commit d89dfc4

Please sign in to comment.