admin/log: country is logged (if geo is enabled)
Massimo Melina committed
Dec 14, 2023 at 11:25 UTC
f937dfb8483f2ee8ff927c2e7f9728496de7b483
4 files changed
+29
-6
admin/src/LogsPage.ts
+19
-1
@@ -11,6 +11,7 @@ import { GridColDef } from '@mui/x-data-grid'
11
import _ from 'lodash'
12
import { SmartToy } from '@mui/icons-material'
13
import md from './md'
14
+import { Country } from './MonitorPage'
15
16
export default function LogsPage() {
17
const [tab, setTab] = useState(0)
@@ -36,11 +37,14 @@ export default function LogsPage() {
37
}
38
39
function LogFile({ file, pause, showApi }: { file: string, pause?: boolean, showApi: boolean }) {
40
+ const [showCountry, setShowCountry] = useState(false)
41
const { list, error, connecting } = useApiList('get_log', { file }, {
42
invert: true,
43
pause,
44
map(x) {
45
const { extra } = x
46
+ if (extra?.country && !showCountry)
47
+ setShowCountry(true)
48
x.notes = extra?.dl ? "fully downloaded"
49
: extra?.ul ? "uploaded " + formatBytes(extra.size)
50
: x.status === HTTP_UNAUTHORIZED && x.uri?.startsWith(API_URL + 'loginSrp') ? "login failed" + prefix(':\n', extra?.u)
@@ -87,7 +91,21 @@ function LogFile({ file, pause, showApi }: { file: string, pause?: boolean, show
91
flex: .6,
92
minWidth: 100,
93
maxWidth: 230,
90
- mergeRender: { other: 'user' },
94
+ mergeRender: {
95
+ other: 'user',
96
+ display: 'flex',
97
+ justifyContent: 'space-between',
98
+ gap: '.5em',
99
+ override: { renderCell: ({ value, row }) => h(Fragment, {}, h('span', {}, value), h(Country, { code: row.extra?.country })) }
100
+ },
101
+ },
102
+ {
103
+ headerName: "Country",
104
+ field: 'country',
105
+ valueGetter: ({ row }) => row.extra?.country,
106
+ hidden: !showCountry,
107
+ hideUnder: 'lg',
108
+ renderCell: ({ value }) => h(Country, { code: value, def: '-' }),
109
},
110
{
111
field: 'user',
admin/src/MonitorPage.ts
+1
-1
@@ -83,7 +83,7 @@ function MoreInfo() {
83
84
}
85
86
-function Country({ code, ip, def }: { code: string, ip?: string, def: ReactNode }) {
86
+export function Country({ code, ip, def }: { code: string, ip?: string, def?: ReactNode }) {
87
const { data } = useBatch(code === undefined && ip && ip2countryBatch, ip, { delay: 100 }) // query if necessary
88
code ||= data || ''
89
const country = code && _.find(COUNTRIES, { code })
src/geo.ts
+4
-3
@@ -17,12 +17,13 @@ setInterval(checkFiles, DAY) // keep updated at run-time
17
export const ip2country = _.memoize((ip: string) => ip2location.getCountryShortAsync(ip).then(v => v === '-' ? '' : v, () => ''))
18
19
export const geoFilter: Middleware = async (ctx, next) => {
20
- if (allow.get() !== null && !isLocalHost(ctx)) {
20
+ if (enabled.get() && !isLocalHost(ctx)) {
21
const { connection } = ctx.state
22
const country = connection.country ??= await ip2country(ctx.ip)
23
updateConnection(connection, { country })
24
- if (country ? list.get().includes(country) !== allow.get() : !allowUnknown.get())
25
- return disconnect(ctx)
24
+ if (allow.get() !== null)
25
+ if (country ? list.get().includes(country) !== allow.get() : !allowUnknown.get())
26
+ return disconnect(ctx)
27
}
28
return next()
29
}
src/log.ts
+5
-1
@@ -11,6 +11,7 @@ import { createFileWithPath, prepareFolder } from './util-files'
11
import { getCurrentUsername } from './auth'
12
import { DAY, makeNetMatcher, tryJson } from './misc'
13
import events from './events'
14
+import { getConnection } from './connections'
15
16
class Logger {
17
stream?: Writable
@@ -106,7 +107,10 @@ export const logMw: Koa.Middleware = async (ctx, next) => {
107
const uri = ctx.originalUrl
108
let extra = ctx.state.includesLastByte && ctx.vfsNode && ctx.res.finished && { dl: 1 }
109
|| ctx.state.uploadPath && { ul: ctx.state.uploadPath, size: ctx.state.uploadSize }
109
- || ctx.state.logExtra
110
+ const conn = getConnection(ctx)
111
+ if (conn?.country)
112
+ Object.assign(extra ||= {}, { country: conn.country })
113
+ extra = extra ? Object.assign(extra, ctx.state.logExtra) : ctx.state.logExtra
114
if (logUA.get())
115
extra = Object.assign({ ua: ctx.get('user-agent') }, extra)
116
events.emit(logger.name, Object.assign(_.pick(ctx, ['ip', 'method','status']), { length, user, ts: now, uri, extra }))