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