admin/monitoring: disconnect-all button #797
Massimo Melina committed
Nov 5, 2024 at 16:38 UTC
0602853caa5053bf4e02f0093deaef85d045fb35
3 files changed
+21
-9
admin/src/MonitorPage.ts
+15
-6
@@ -3,7 +3,7 @@
3
import _ from "lodash"
4
import { createElement as h, useMemo, Fragment, useState } from "react"
5
import { apiCall, useApiEvents, useApiEx, useApiList } from "./api"
6
-import { LinkOff, Lock, FolderZip, Upload, Download, ChevronRight, ChevronLeft, History } from '@mui/icons-material'
6
+import { LinkOff as DisconnectIcon, Lock, FolderZip, Upload, Download, ChevronRight, ChevronLeft, History } from '@mui/icons-material'
7
import { Alert, Box, Chip, ChipProps, Grid } from '@mui/material'
8
import { DataTable } from './DataTable'
9
import {
@@ -11,14 +11,14 @@ import {
11
reactJoin,
12
} from "./misc"
13
import {
14
- IconBtn, IconProgress, iconTooltip, usePauseButton, useBreakpoint, Country, hTooltip, useToggleButton, Flex
14
+ IconBtn, IconProgress, iconTooltip, usePauseButton, useBreakpoint, Country, hTooltip, useToggleButton, Flex, Btn
15
} from './mui'
16
import { Field, SelectField } from '@hfs/mui-grid-form'
17
import { StandardCSSProperties } from '@mui/system/styleFunctionSx/StandardCssProperties'
18
import { agentIcons, LogFile } from './LogsPage'
19
import { state, useSnapState } from './state'
20
import { useBlockIp } from './useBlockIp'
21
-import { alertDialog, confirmDialog } from './dialog'
21
+import { alertDialog, confirmDialog, toast } from './dialog'
22
import { useInterval } from 'usehooks-ts'
23
import { PageProps } from './App'
24
@@ -129,7 +129,7 @@ function Connections() {
129
const logSize = logAble && wantLog ? 6 : 0
130
return h(Fragment, {},
131
h(Flex, {},
132
- h(Box, { flex: 1 },
132
+ h(Flex, { flex: 1 },
133
h(SelectField as Field<boolean>, {
134
fullWidth: false,
135
value: monitorOnlyFiles,
@@ -147,7 +147,16 @@ function Connections() {
147
error,
148
rows,
149
noRows: monitorOnlyFiles && "No downloads at the moment",
150
- footerSide: () => pauseButton,
150
+ footerSide: () => h(Flex, {},
151
+ pauseButton,
152
+ h(Btn, {
153
+ size: 'small',
154
+ icon: DisconnectIcon,
155
+ labelIf: 'xl',
156
+ confirm: "Disconnecting all connections but localhost. Continue?",
157
+ onClick: () => apiCall('disconnect', { allButLocalhost: true }).then(x => toast(`Disconnected: ${x.result}`))
158
+ }, "Disconnect all")
159
+ ),
160
columns: [
161
{
162
field: 'ip',
@@ -249,7 +258,7 @@ function Connections() {
258
actionsProps: { hideUnder: 'sm' },
259
actions: ({ row }) => [
260
h(IconBtn, {
252
- icon: LinkOff,
261
+ icon: DisconnectIcon,
262
title: "Disconnect",
263
doneMessage: true,
264
onClick: () => apiCall('disconnect', _.pick(row, ['ip', 'port'])).then(x => x.result > 0)
admin/src/mui.ts
+2
@@ -148,6 +148,8 @@ export const Btn = forwardRef(({ icon, title, onClick, disabled, progress, link,
148
if (link)
149
onClick = () => window.open(link)
150
const showLabel = useBreakpoint(_.isString(labelIf) ? labelIf : 'xs') && (_.isBoolean(labelIf) ? labelIf : true)
151
+ if (!showLabel)
152
+ title = children
153
const ref = useRefPass<HTMLButtonElement>(forwarded)
154
const common = _.merge(propsForModifiedValues(modified), {
155
ref,
src/api.monitor.ts
+4
-3
@@ -2,7 +2,7 @@
2
3
import _ from 'lodash'
4
import { Connection, getConnections } from './connections'
5
-import { apiAssertTypes, shortenAgent, try_, wait, wantArray } from './misc'
5
+import { apiAssertTypes, isLocalHost, shortenAgent, try_, wait, wantArray } from './misc'
6
import { ApiHandlers } from './apiMiddleware'
7
import Koa from 'koa'
8
import { totalGot, totalInSpeed, totalOutSpeed, totalSent } from './throttler'
@@ -12,8 +12,9 @@ import { storedMap } from './persistence'
12
13
export default {
14
15
- async disconnect({ ip, port }) {
16
- const match = _.matches({ ip, port })
15
+ async disconnect({ ip, port, allButLocalhost }) {
16
+ const match = allButLocalhost ? ((x: any) => !isLocalHost(x.ip))
17
+ : _.matches({ ip, port })
18
const found = getConnections().filter(c => match(getConnAddress(c)))
19
for (const c of found)
20
c.socket.destroy()