admin: don't ask for login if no login is possible
Massimo Melina committed
Jan 26, 2023 at 16:41 UTC
52dfb6a124ac8c743f73905afeafd55d4daef886
8 files changed
+22
-9
admin/src/LoginRequired.ts
+6
-1
@@ -6,10 +6,15 @@ import { Center } from './misc'
6
import { Form } from '@hfs/mui-grid-form'
7
import { apiCall } from './api'
8
import { srpSequence } from '@hfs/shared'
9
-import { Alert } from '@mui/material'
9
+import { Alert, Box } from '@mui/material'
10
11
export function LoginRequired({ children }: any) {
12
const { loginRequired } = useSnapState()
13
+ if (loginRequired === 403)
14
+ return h(Center, {},
15
+ h(Alert, { severity: 'error' }, "Admin-panel only for localhost"),
16
+ h(Box, { mt: 2, fontSize: 'small' }, "because no admin account was configured")
17
+ )
18
if (loginRequired)
19
return h(LoginForm)
20
return h(Fragment, {}, children)
admin/src/api.ts
+2
-1
@@ -7,6 +7,7 @@ import _ from 'lodash'
7
import { state } from './state'
8
import { Refresh } from '@mui/icons-material'
9
import produce, { Draft } from 'immer'
10
+import { try_ } from './misc'
11
12
export function useApiEx<T=any>(...args: Parameters<typeof useApi>) {
13
const [data, error, reload] = useApi<T>(...args)
@@ -48,7 +49,7 @@ export function apiCall(cmd: string, params?: Dict, { timeout=undefined }={}) :
49
const msg = await res.text() || 'Failed API ' + cmd
50
console.warn(msg + (params ? ' ' + JSON.stringify(params) : ''))
51
if (res.status === 401)
51
- state.loginRequired = true
52
+ state.loginRequired = Boolean(try_(() => JSON.parse(msg)?.any)) || 403
53
throw new ApiError(res.status, msg)
54
}, err => {
55
if (err?.message?.includes('fetch'))
admin/src/misc.ts
+1
-1
@@ -78,7 +78,7 @@ export function InLink(props:any) {
78
}
79
80
export function Center(props: any) {
81
- return h(Box, { display:'flex', height:'100%', width:'100%', justifyContent:'center', alignItems:'center', ...props })
81
+ return h(Box, { display:'flex', height:'100%', width:'100%', justifyContent:'center', alignItems:'center', flexDirection: 'column', ...props })
82
}
83
84
export async function manipulateConfig(k: string, work:(data:any) => any) {
admin/src/state.ts
+1
-1
@@ -12,7 +12,7 @@ export const state = proxy<{
12
config: Dict
13
vfs: VfsNode | undefined
14
selectedFiles: VfsNode[]
15
- loginRequired: boolean
15
+ loginRequired: boolean | number
16
username: string
17
onlinePluginsColumns: Dict<boolean>
18
}>(Object.assign({
shared/index.ts
+8
@@ -72,3 +72,11 @@ export function setHidden(dest: object, src:object) {
72
})))
73
}
74
75
+export function try_(cb: () => any, onException?: (e:any) => any) {
76
+ try {
77
+ return cb()
78
+ }
79
+ catch(e) {
80
+ return onException?.(e)
81
+ }
82
+}
\ No newline at end of file
src/adminApis.ts
+2
-2
@@ -23,7 +23,7 @@ import { getConnections } from './connections'
23
import { debounceAsync, isLocalHost, onOff, wait } from './misc'
24
import _ from 'lodash'
25
import events from './events'
26
-import { getFromAccount } from './perm'
26
+import { anyAccountCanLoginAdmin, getFromAccount } from './perm'
27
import Koa from 'koa'
28
import { getProxyDetected } from './middlewares'
29
import { writeFile } from 'fs/promises'
@@ -144,7 +144,7 @@ export const adminApis: ApiHandlers = {
144
for (const [k, was] of Object.entries(adminApis))
145
adminApis[k] = (params, ctx) =>
146
ctxAdminAccess(ctx) ? was(params, ctx)
147
- : new ApiError(HTTP_UNAUTHORIZED)
147
+ : new ApiError(HTTP_UNAUTHORIZED, { any: anyAccountCanLoginAdmin() })
148
149
export const localhostAdmin = defineConfig('localhost_admin', true)
150
src/apiMiddleware.ts
+2
-2
@@ -9,8 +9,8 @@ import { HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_UNAUTHORIZED } from './const'
9
import _, { DebouncedFunc } from 'lodash'
10
11
export class ApiError extends Error {
12
- constructor(public status:number, message?:string | Error) {
13
- super(typeof message === 'string' ? message : message?.message)
12
+ constructor(public status:number, message?:string | Error | object) {
13
+ super(typeof message === 'string' ? message : message && message instanceof Error ? message.message : JSON.stringify(message))
14
}
15
}
16
type ApiHandlerResult = Record<string,any> | ApiError | Readable | AsyncGenerator<any>
src/const.ts
-1
@@ -5,7 +5,6 @@ import * as fs from 'fs'
5
import { homedir } from 'os'
6
import { mkdirSync } from 'fs'
7
import { basename, dirname, join } from 'path'
8
-import http2 from 'http2'
8
9
export const argv = minimist(process.argv.slice(2))
10
export const DEV = process.env.DEV || argv.dev ? 'DEV' : ''