From 354770279b7c54324ae4f251317a788c7fe68e05 Mon Sep 17 00:00:00 2001 From: DomySh Date: Fri, 12 Aug 2022 18:51:50 +0000 Subject: [PATCH] Port hijack frontend finished --- frontend/src/components/PortAndInterface.tsx | 2 +- .../components/PortHijack/AddNewService.tsx | 2 +- .../PortHijack/ServiceRow/index.module.scss | 10 +- .../PortHijack/ServiceRow/index.tsx | 173 ++++++++++-------- frontend/src/components/PortInput.tsx | 31 ++-- .../components/RegexProxy/AddNewService.tsx | 4 +- .../RegexProxy/ServiceRow/ChangePortModal.tsx | 6 +- frontend/src/js/utils.tsx | 4 +- 8 files changed, 137 insertions(+), 95 deletions(-) diff --git a/frontend/src/components/PortAndInterface.tsx b/frontend/src/components/PortAndInterface.tsx index 77e0669..3d010cb 100644 --- a/frontend/src/components/PortAndInterface.tsx +++ b/frontend/src/components/PortAndInterface.tsx @@ -40,7 +40,7 @@ export default function PortAndInterface({ form, int_name, port_name, label }:{ style={{width:"100%"}} /> : - + } \ No newline at end of file diff --git a/frontend/src/components/PortHijack/AddNewService.tsx b/frontend/src/components/PortHijack/AddNewService.tsx index e850523..a094184 100755 --- a/frontend/src/components/PortHijack/AddNewService.tsx +++ b/frontend/src/components/PortHijack/AddNewService.tsx @@ -1,4 +1,4 @@ -import { Button, Group, Space, TextInput, Notification, Modal, Switch, SegmentedControl, Autocomplete } from '@mantine/core'; +import { Button, Group, Space, TextInput, Notification, Modal, Switch, SegmentedControl } from '@mantine/core'; import { useForm } from '@mantine/hooks'; import React, { useState } from 'react'; import { okNotify, regex_ipv6_no_cidr, regex_ipv4_no_cidr } from '../../js/utils'; diff --git a/frontend/src/components/PortHijack/ServiceRow/index.module.scss b/frontend/src/components/PortHijack/ServiceRow/index.module.scss index 0d91313..69834c0 100755 --- a/frontend/src/components/PortHijack/ServiceRow/index.module.scss +++ b/frontend/src/components/PortHijack/ServiceRow/index.module.scss @@ -3,7 +3,7 @@ .row{ width: 95%; - padding: 30px 0px; + padding: 15px 0px; border-radius: 20px; margin: 10px; @extend .center-flex; @@ -15,4 +15,12 @@ margin-right: 10px; margin-bottom: 13px; color:#FFF; +} + +.portInput *{ + color: #FFF; + font-weight: bold; + font-size: 1em; + margin-top: -1px; + text-decoration: underline; } \ No newline at end of file diff --git a/frontend/src/components/PortHijack/ServiceRow/index.tsx b/frontend/src/components/PortHijack/ServiceRow/index.tsx index 2810102..3dbee0e 100755 --- a/frontend/src/components/PortHijack/ServiceRow/index.tsx +++ b/frontend/src/components/PortHijack/ServiceRow/index.tsx @@ -1,14 +1,16 @@ -import { ActionIcon, Badge, Divider, Grid, MediaQuery, Menu, Space, Title, Tooltip } from '@mantine/core'; +import { ActionIcon, Badge, Divider, Menu, Space, Title, Tooltip } from '@mantine/core'; import React, { useState } from 'react'; import { FaPlay, FaStop } from 'react-icons/fa'; import { porthijack, Service } from '../utils'; import style from "./index.module.scss"; import YesNoModal from '../../YesNoModal'; -import { errorNotify, okNotify, regex_ipv4 } from '../../../js/utils'; +import { errorNotify, okNotify } from '../../../js/utils'; import { BsArrowRepeat, BsTrashFill } from 'react-icons/bs'; import { BiRename } from 'react-icons/bi' import RenameForm from './RenameForm'; import ChangeDestination from './ChangeDestination'; +import PortInput from '../../PortInput'; +import { useForm } from '@mantine/hooks'; function ServiceRow({ service }:{ service:Service }) { @@ -19,6 +21,30 @@ function ServiceRow({ service }:{ service:Service }) { const [deleteModal, setDeleteModal] = useState(false) const [renameModal, setRenameModal] = useState(false) const [changeDestModal, setChangeDestModal] = useState(false) + const portInputRef = React.createRef() + + const form = useForm({ + initialValues: { proxy_port:service.proxy_port }, + validationRules:{ proxy_port: (value) => value > 0 && value < 65536 } + }) + + const onChangeProxyPort = ({proxy_port}:{proxy_port:number}) => { + if (proxy_port === service.proxy_port) return + if (proxy_port > 0 && proxy_port < 65536 && proxy_port !== service.public_port){ + porthijack.changedestination(service.service_id, service.ip_dst, proxy_port).then( res => { + if (res.status === "ok"){ + okNotify(`Service ${service.name} destination port has changed in ${ proxy_port }`, `Successfully changed destination port`) + }else{ + errorNotify(`Error while changing the destination port of ${service.name}`,`Error: ${res.status}`) + } + }).catch( err => { + errorNotify("Request for changing port failed!",`Error: [ ${err} ]`) + }) + }else{ + form.setFieldValue("proxy_port", service.proxy_port) + errorNotify(`Error while changing the destination port of ${service.name}`,`Insert a valid port number`) + } + } const stopService = async () => { setButtonLoading(true) @@ -62,80 +88,81 @@ function ServiceRow({ service }:{ service:Service }) { } return <> - - -
-
-
{service.name} :{service.public_port}
- Status: {service.active?"ENABLED":"DISABLED"} -
-
-
-
-
{service.name} :{service.public_port}
- Status: {service.active?"ENABLED":"DISABLED"} - -
-
- - - - -
- - - -
- - - <> - - +
+ +
- {service.ip_src} on {service.proto} +
{service.name} :{service.public_port}
+
+ Status: {service.active?"ENABLED":"DISABLED"} + + + {service.proto} + +
- -
- - - <> - -
- - Rename service - } onClick={()=>setRenameModal(true)}>Change service name - Change destination - } onClick={()=>setChangeDestModal(true)}>Change hijacking destination - - Danger zone - } onClick={()=>setDeleteModal(true)}>Delete Service - - - - setTooltipStopOpened(false)} onBlur={() => setTooltipStopOpened(false)} - onMouseEnter={() => setTooltipStopOpened(true)} onMouseLeave={() => setTooltipStopOpened(false)}> - - - - - - - - - -
- - - <> - +
+ +
+
+ + FROM {service.ip_src} : {service.public_port} + + + +
+ TO {service.ip_dst} : +
portInputRef.current?.blur())}> + {onChangeProxyPort({proxy_port:parseInt(e.target.value)})}} + ref={portInputRef} + {...form.getInputProps("proxy_port")} + /> + +
+
+
+ + +
+ + Rename service + } onClick={()=>setRenameModal(true)}>Change service name + Change destination + } onClick={()=>setChangeDestModal(true)}>Change hijacking destination + + Danger zone + } onClick={()=>setDeleteModal(true)}>Delete Service + + + + setTooltipStopOpened(false)} onBlur={() => setTooltipStopOpened(false)} + onMouseEnter={() => setTooltipStopOpened(true)} onMouseLeave={() => setTooltipStopOpened(false)}> + + + + + + + + + +
+ - - +

, defaultValue?:number, label?:React.ReactNode, others:any, fullWidth?:boolean }) { - const [oldValue, setOldValue] = useState(defaultValue?defaultValue.toString():"") +interface PortInputProps extends NumberInputProps { + fullWidth?: boolean +} + +const PortInput = React.forwardRef( (props, ref) => { + + const [oldValue, setOldValue] = useState(props.defaultValue?props.defaultValue.toString():"") return { const value = parseInt((e.target as HTMLInputElement).value) if (value > 65535) { @@ -22,8 +25,12 @@ export default function PortInput({ onInput, defaultValue, others, label, fullWi (e.target as HTMLInputElement).value = value.toString() } setOldValue((e.target as HTMLInputElement).value) - onInput?.(e) + props.onInput?.(e) }} - {...others} + ref={ref} + {...props} /> -} \ No newline at end of file + +}) + +export default PortInput \ No newline at end of file diff --git a/frontend/src/components/RegexProxy/AddNewService.tsx b/frontend/src/components/RegexProxy/AddNewService.tsx index c20de9c..593f9b1 100755 --- a/frontend/src/components/RegexProxy/AddNewService.tsx +++ b/frontend/src/components/RegexProxy/AddNewService.tsx @@ -71,7 +71,7 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) {form.values.chosenInternalPort?<> @@ -79,7 +79,7 @@ function AddNewService({ opened, onClose }:{ opened:boolean, onClose:()=>void }) :null} diff --git a/frontend/src/components/RegexProxy/ServiceRow/ChangePortModal.tsx b/frontend/src/components/RegexProxy/ServiceRow/ChangePortModal.tsx index aec91c0..5b7106c 100755 --- a/frontend/src/components/RegexProxy/ServiceRow/ChangePortModal.tsx +++ b/frontend/src/components/RegexProxy/ServiceRow/ChangePortModal.tsx @@ -1,4 +1,4 @@ -import { Button, Group, NumberInput, Space, Notification, Modal, Center, Title } from '@mantine/core'; +import { Button, Group, Space, Notification, Modal, Center, Title } from '@mantine/core'; import { useForm } from '@mantine/hooks'; import React, { useEffect, useState } from 'react'; import { ImCross } from "react-icons/im" @@ -62,7 +62,7 @@ function ChangePortModal({ service, opened, onClose }:{ service:Service, opened: @@ -71,7 +71,7 @@ function ChangePortModal({ service, opened, onClose }:{ service:Service, opened: diff --git a/frontend/src/js/utils.tsx b/frontend/src/js/utils.tsx index cf44275..239aa5f 100755 --- a/frontend/src/js/utils.tsx +++ b/frontend/src/js/utils.tsx @@ -12,8 +12,8 @@ export const eventUpdateName = "update-info" export const regex_ipv6 = "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$"; export const regex_ipv6_no_cidr = "^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*$"; -export const regex_ipv4 = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(3[0-2]|[1-2][0-9]|[0-9]))?$" -export const regex_ipv4_no_cidr = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" +export const regex_ipv4 = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(3[0-2]|[1-2][0-9]|[0-9]))?$" +export const regex_ipv4_no_cidr = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" export async function getapi(path:string):Promise{