better code: centralize admin_net check
Massimo Melina committed
Jun 21, 2025 at 14:41 UTC
a6385bbea021bfd06a9a830367b5e14e1944150e
2 files changed
+8
-9
src/adminApis.ts
+6
-6
@@ -177,8 +177,6 @@ export const adminApis = {
177
178
for (const [k, was] of typedEntries(adminApis))
179
(adminApis[k] as any) = ((params, ctx) => {
180
- if (!allowAdmin(ctx))
181
- return new ApiError(HTTP_FORBIDDEN)
180
if (ctxAdminAccess(ctx))
181
return was(params, ctx)
182
const props = { possible: anyAccountCanLoginAdmin() }
@@ -193,8 +191,10 @@ export const favicon = defineConfig('favicon', '')
191
export const title = defineConfig('title', "File server")
192
193
export function ctxAdminAccess(ctx: Koa.Context) {
196
- return !ctx.ips.length // we consider localhost_admin only if no proxy is being used
197
- && localhostAdmin.get() && isLocalHost(ctx)
194
+ if (preventAdminAccess(ctx))
195
+ return false
196
+ // for extra security, skip localhost_admin via proxy, even tho this prevents using it with local proxies, which is legit in principle
197
+ return !ctx.ips.length && localhostAdmin.get() && isLocalHost(ctx)
198
|| ctx.state.account && accountCanLoginAdmin(ctx.state.account)
199
}
200
@@ -213,6 +213,6 @@ export function anyAccountCanLoginAdmin() {
213
return Boolean(_.find(accounts.get(), accountCanLoginAdmin))
214
}
215
216
-export function allowAdmin(ctx: Koa.Context) {
217
- return isLocalHost(ctx) || adminNet.compiled()(ctx.ip)
216
+export function preventAdminAccess(ctx: Koa.Context) {
217
+ return !isLocalHost(ctx) && !adminNet.compiled()(ctx.ip)
218
}
\ No newline at end of file
src/serveGuiAndSharedFiles.ts
+2
-3
@@ -13,7 +13,7 @@ import { Writable } from 'stream'
13
import { serveFile, serveFileNode } from './serveFile'
14
import { BUILD_TIMESTAMP, DEV, MIME_AUTO, VERSION } from './const'
15
import { zipStreamFromFolder } from './zip'
16
-import { allowAdmin, favicon } from './adminApis'
16
+import { preventAdminAccess, favicon } from './adminApis'
17
import { serveGuiFiles } from './serveGuiFiles'
18
import mount from 'koa-mount'
19
import { baseUrl } from './listen'
@@ -42,8 +42,7 @@ export const serveGuiAndSharedFiles: Koa.Middleware = async (ctx, next) => {
42
if (path.length === ADMIN_URI.length - 1 && ADMIN_URI.startsWith(path))
43
return ctx.redirect(ctx.state.revProxyPath + ADMIN_URI)
44
if (path.startsWith(ADMIN_URI))
45
- return allowAdmin(ctx) ? serveAdminPrefixed(ctx,next)
46
- : sendErrorPage(ctx, HTTP_FORBIDDEN)
45
+ return preventAdminAccess(ctx) ? sendErrorPage(ctx, HTTP_FORBIDDEN) : serveAdminPrefixed(ctx, next)
46
if (path.startsWith(ICONS_URI)) {
47
const a = path.substring(ICONS_URI.length).split('/')
48
const iconName = a.at(-1)