fix: admin: no login dialog if accessing plugins page on small screens
Massimo Melina committed
Jan 27, 2023 at 22:44 UTC
9bfcc41d85fe52b55c81cc69e264ca3c80684745
4 files changed
+28
-20
admin/src/api.ts
+18
-13
@@ -177,28 +177,33 @@ export function useApiList<T=any>(cmd:string|Falsy, params: Dict={}, { addId=fal
177
case 'closed':
178
return stop()
179
case 'msg':
180
- wantArray(data).forEach(data => {
181
- if (data === 'ready') {
180
+ wantArray(data).forEach(entry => {
181
+ if (entry === 'ready') {
182
apply.flush()
183
setInitializing(false)
184
return
185
}
186
- if (data.error)
187
- return setError(err2msg(data.error))
188
- if (data.props)
189
- return setProps(data.props)
190
- if (data.add) {
191
- const rec = map(data.add)
186
+ if (entry.error) {
187
+ if (entry.error === 401)
188
+ state.loginRequired = entry.any || 403
189
+ else
190
+ setError(err2msg(entry.error))
191
+ return
192
+ }
193
+ if (entry.props)
194
+ return setProps(entry.props)
195
+ if (entry.add) {
196
+ const rec = map(entry.add)
197
if (addId)
198
rec.id = ++idRef.current
199
buffer.push(rec)
200
apply()
201
return
202
}
198
- if (data.remove) {
203
+ if (entry.remove) {
204
const matchOnList: ReturnType<typeof _.matches>[] = []
205
// first remove from the buffer
201
- for (const key of data.remove) {
206
+ for (const key of entry.remove) {
207
const match1 = _.matches(key)
208
if (_.isEmpty(_.remove(buffer, match1)))
209
matchOnList.push(match1)
@@ -212,11 +217,11 @@ export function useApiList<T=any>(cmd:string|Falsy, params: Dict={}, { addId=fal
217
})
218
return
219
}
215
- if (data.update) {
220
+ if (entry.update) {
221
apply.flush() // avoid treating buffer
222
setList(list => {
223
const modified = [...list]
219
- for (const { search, change } of data.update) {
224
+ for (const { search, change } of entry.update) {
225
const idx = modified.findIndex(_.matches(search))
226
if (idx >= 0)
227
modified[idx] = { ...modified[idx], ...change }
@@ -225,7 +230,7 @@ export function useApiList<T=any>(cmd:string|Falsy, params: Dict={}, { addId=fal
230
})
231
return
232
}
228
- console.debug('unknown api event', type, data)
233
+ console.debug('unknown api event', type, entry)
234
})
235
if (src?.readyState === src?.CLOSED)
236
stop()
src/adminApis.ts
+8
-3
@@ -142,9 +142,14 @@ export const adminApis: ApiHandlers = {
142
}
143
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, { any: anyAccountCanLoginAdmin() })
145
+ adminApis[k] = (params, ctx) => {
146
+ if (ctxAdminAccess(ctx))
147
+ return was(params, ctx)
148
+ const props = { any: anyAccountCanLoginAdmin() }
149
+ return ctx.headers.accept === 'text/event-stream'
150
+ ? new SendListReadable({ doAtStart: x => x.error(HTTP_UNAUTHORIZED, true, props) })
151
+ : new ApiError(HTTP_UNAUTHORIZED, props)
152
+ }
153
154
export const localhostAdmin = defineConfig('localhost_admin', true)
155
src/apiMiddleware.ts
+2
-2
@@ -107,8 +107,8 @@ export class SendListReadable<T> extends Readable {
107
props(props: object) {
108
this._push({ props })
109
}
110
- error(msg: NonNullable<typeof this.lastError>, close=false) {
111
- this._push({ error: msg })
110
+ error(msg: NonNullable<typeof this.lastError>, close=false, props?: object) {
111
+ this._push({ error: msg, ...props })
112
this.lastError = msg
113
if (close)
114
this.close()
src/index.ts
-2
@@ -17,7 +17,6 @@ import { defineConfig } from './config'
17
import { ok } from 'assert'
18
import _ from 'lodash'
19
import { randomId } from './misc'
20
-//import body from 'koa-better-body'
20
21
ok(_.intersection(Object.keys(frontEndApis), Object.keys(adminApis)).length === 0) // they share same endpoints
22
@@ -32,7 +31,6 @@ app.use(someSecurity)
31
.use(gzipper)
32
.use(pluginsMiddleware())
33
.use(mount(API_URI, apiMiddleware({ ...frontEndApis, ...adminApis })))
35
- //.use(body({ multipart: false }))
34
.use(serveGuiAndSharedFiles)
35
.on('error', errorHandler)
36