@samitouri / QOSami-HFS / commits / 5c5b0288

better code: use constants

Massimo Melina committed Nov 15, 2023 at 20:32 UTC 5c5b0288302b04a476f1d492915b3e047e8548dd
10 files changed +36 -32
admin/src/AccountForm.ts
+4 -4
@@ -2,11 +2,11 @@
2
3 import { createElement as h, ReactNode, useEffect, useRef, useState } from 'react'
4 import { BoolField, Form, MultiSelectField } from '@hfs/mui-grid-form'
5 -import { Alert, Box } from '@mui/material'
5 +import { Alert } from '@mui/material'
6 import { apiCall } from './api'
7 import { alertDialog, toast, useDialogBarColors } from './dialog'
8 -import { IconBtn, isEqualLax, modifiedSx, wantArray } from './misc'
9 -import { Account, account2icon } from './AccountsPage'
8 +import { HTTP_NOT_ACCEPTABLE, IconBtn, isEqualLax, modifiedSx, wantArray } from './misc'
9 +import { Account } from './AccountsPage'
10 import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
11 import { AutoDelete, Delete } from '@mui/icons-material'
12 import { isMobile } from './misc'
@@ -110,7 +110,7 @@ export async function apiNewPassword(username: string, password: string) {
110 const srp6aNimbusRoutines = new SRPRoutines(new SRPParameters())
111 const res = await createVerifierAndSalt(srp6aNimbusRoutines, username, password)
112 return apiCall('change_srp_others', { username, salt: String(res.s), verifier: String(res.v) }).catch(e => {
113 - if (e.code !== 406) // 406 = server was configured to support clear text authentication
113 + if (e.code !== HTTP_NOT_ACCEPTABLE) // server doesn't support clear text authentication
114 throw e
115 return apiCall('change_password_others', { username, newPassword: password }) // unencrypted version
116 })
admin/src/InstalledPlugins.ts
+2 -2
@@ -5,7 +5,7 @@ import { createElement as h, Fragment, ReactNode } from 'react'
5 import { Box, Link, Tooltip } from '@mui/material'
6 import { DataTable } from './DataTable'
7 import { Delete, Error as ErrorIcon, PlayCircle, Settings, StopCircle, Upgrade } from '@mui/icons-material'
8 -import { Btn, IconBtn, prefix, with_ } from './misc'
8 +import { Btn, HTTP_FAILED_DEPENDENCY, IconBtn, prefix, with_ } from './misc'
9 import { alertDialog, formDialog, toast } from './dialog'
10 import _ from 'lodash'
11 import { BoolField, Field, MultiSelectField, NumberField, SelectField, StringField } from '@hfs/mui-grid-form'
@@ -51,7 +51,7 @@ export default function InstalledPlugins({ updates }: { updates?: true }) {
51 size,
52 async onClick() {
53 await apiCall('update_plugin', { id }, { timeout: false }).catch(e => {
54 - throw e.code !== 424 ? e
54 + throw e.code !== HTTP_FAILED_DEPENDENCY ? e
55 : Error("Failed dependencies: " + e.cause?.map((x: any) => prefix(`plugin "`, x.id || x.repo, `" `) + x.error).join('; '))
56 })
57 updateEntry({ id }, { updated: true })
admin/src/LoginRequired.ts
+3 -3
@@ -2,7 +2,7 @@
2
3 import { state, useSnapState } from './state'
4 import { createElement as h, Fragment, useEffect, useRef, useState } from 'react'
5 -import { Center, getHFS, makeSessionRefresher } from './misc'
5 +import { Center, getHFS, HTTP_FORBIDDEN, HTTP_UNAUTHORIZED, makeSessionRefresher } from './misc'
6 import { Form } from '@hfs/mui-grid-form'
7 import { apiCall } from './api'
8 import { srpClientSequence } from '@hfs/shared'
@@ -10,7 +10,7 @@ import { Alert, Box } from '@mui/material'
10
11 export function LoginRequired({ children }: any) {
12 const { loginRequired } = useSnapState()
13 - if (loginRequired === 403)
13 + if (loginRequired === HTTP_FORBIDDEN)
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")
@@ -58,7 +58,7 @@ function LoginForm() {
58
59 async function login(username: string, password: string) {
60 const res = await srpClientSequence(username, password, apiCall).catch(err => {
61 - throw err?.code === 401 ? "Wrong username or password"
61 + throw err?.code === HTTP_UNAUTHORIZED ? "Wrong username or password"
62 : err === 'trust' ? "Login aborted: server identity cannot be trusted"
63 : err?.name === 'AbortError' ? "Server didn't respond"
64 : (err?.message || "Unknown error")
admin/src/LogoutPage.ts
+2 -2
@@ -5,7 +5,7 @@ import { Alert, Box } from '@mui/material'
5 import { apiCall, useApiEx } from './api'
6 import { alertDialog } from "./dialog"
7 import { useSnapState } from './state'
8 -import { Btn } from './misc'
8 +import { Btn, HTTP_UNAUTHORIZED } from './misc'
9 import { Logout, PowerSettingsNew } from '@mui/icons-material'
10
11 export default function LogoutPage() {
@@ -22,7 +22,7 @@ export default function LogoutPage() {
22 size: 'large',
23 variant: 'contained',
24 onClick: () => apiCall('logout').catch(err => // we expect 401
25 - err.code !== 401 && alertDialog(err))
25 + err.code !== HTTP_UNAUTHORIZED && alertDialog(err))
26 }, "I want to logout")
27 ),
28 h(Btn, {
admin/src/api.ts
+6 -5
@@ -1,7 +1,8 @@
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 import { createElement as h, useEffect, useMemo, useRef, useState } from 'react'
4 -import { Dict, err2msg, Falsy, IconBtn, LIST, spinner, useStateMounted, wantArray, xlate } from './misc'
4 +import { Dict, err2msg, Falsy, IconBtn, LIST, spinner, useStateMounted, wantArray, xlate,
5 + HTTP_FORBIDDEN, HTTP_UNAUTHORIZED,} from './misc'
6 import { Alert } from '@mui/material'
7 import _ from 'lodash'
8 import { state } from './state'
@@ -12,8 +13,8 @@ export * from '@hfs/shared/api'
13
14 setDefaultApiCallOptions({
15 async onResponse(res: Response, body: any) {
15 - if (res.status === 401) {
16 - state.loginRequired = body?.possible !== false || 403
16 + if (res.status === HTTP_UNAUTHORIZED) {
17 + state.loginRequired = body?.possible !== false || HTTP_FORBIDDEN
18 throw new ApiError(res.status, "Unauthorized")
19 }
20 }
@@ -84,8 +85,8 @@ export function useApiList<T=any, S=T>(cmd:string|Falsy, params: Dict={}, { map,
85 return
86 }
87 if (op === LIST.error) {
87 - if (par === 401)
88 - state.loginRequired = msg[2].possible !== false || 403
88 + if (par === HTTP_UNAUTHORIZED)
89 + state.loginRequired = msg[2].possible !== false || HTTP_FORBIDDEN
90 else
91 setError(err2msg(par))
92 return
admin/src/importAccountsCsv.ts
+2 -2
@@ -4,7 +4,7 @@ import { Group, Upload } from '@mui/icons-material'
4 import { Box } from '@mui/material'
5 import { apiCall } from './api'
6 import { apiNewPassword } from './AccountForm'
7 -import { IconProgress, prefix, readFile, selectFiles } from './misc'
7 +import { HTTP_CONFLICT, IconProgress, prefix, readFile, selectFiles } from './misc'
8 import { NumberField, BoolField } from '@hfs/mui-grid-form'
9 import Parser from '@gregoranders/csv';
10
@@ -90,7 +90,7 @@ export async function importAccountsCsv(cb?: () => void) {
90 if (rec.p)
91 return apiNewPassword(rec.u, rec.p)
92 }, e => {
93 - if (e.code === 409)
93 + if (e.code === HTTP_CONFLICT)
94 return already++
95 bad++
96 })
frontend/src/UserPanel.ts
+2 -2
@@ -7,7 +7,7 @@ import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
7 import { apiCall } from '@hfs/shared/api'
8 import { logout } from './login'
9 import { MenuButton } from './menu'
10 -import { hIcon, working } from './misc'
10 +import { hIcon, HTTP_NOT_ACCEPTABLE, working } from './misc'
11 import { t } from './i18n'
12
13 export default function showUserPanel() {
@@ -35,7 +35,7 @@ export default function showUserPanel() {
35 const res = await createVerifierAndSalt(srp6aNimbusRoutines, snap.username, pwd)
36 try {
37 await apiCall('change_srp', { salt: String(res.s), verifier: String(res.v) }, { modal: working }).catch(e => {
38 - if (e.code !== 406) // 406 = server was configured to support clear text authentication
38 + if (e.code !== HTTP_NOT_ACCEPTABLE) // server doesn't support clear text authentication
39 throw e
40 return apiCall('change_password', { newPassword: pwd }, { modal: working }) // unencrypted version
41 })
frontend/src/login.ts
+5 -4
@@ -3,7 +3,8 @@
3 import { apiCall } from '@hfs/shared/api'
4 import { state, useSnapState } from './state'
5 import { alertDialog, newDialog } from './dialog'
6 -import { getHFS, getPrefixUrl, hIcon, makeSessionRefresher, srpClientSequence, working } from './misc'
6 +import { getHFS, getPrefixUrl, hIcon, makeSessionRefresher, srpClientSequence, working,
7 + HTTP_CONFLICT, HTTP_UNAUTHORIZED,} from './misc'
8 import { useNavigate } from 'react-router-dom'
9 import { createElement as h, Fragment, useEffect, useRef } from 'react'
10 import { t, useI18N } from './i18n'
@@ -21,8 +22,8 @@ async function login(username:string, password:string) {
22 }, (err: any) => {
23 stopWorking()
24 throw Error(err.message === 'trust' ? t('login_untrusted', "Login aborted: server identity cannot be trusted")
24 - : err.code === 401 ? t('login_bad_credentials', "Invalid credentials")
25 - : err.code === 409 ? t('login_bad_cookies', "Cookies not working - login failed")
25 + : err.code === HTTP_UNAUTHORIZED ? t('login_bad_credentials', "Invalid credentials")
26 + : err.code === HTTP_CONFLICT ? t('login_bad_cookies', "Cookies not working - login failed")
27 : t(err.message))
28 })
29 }
@@ -32,7 +33,7 @@ sessionRefresher(getHFS().session)
33
34 export function logout(){
35 return apiCall('logout', {}, { modal: working }).catch(res => {
35 - if (res.code !== 401) // we expect 401
36 + if (res.code !== HTTP_UNAUTHORIZED) // we expect this error code
37 throw res
38 state.username = ''
39 reloadList()
frontend/src/upload.ts
+6 -4
@@ -2,7 +2,9 @@
2
3 import { createElement as h, DragEvent, Fragment, useMemo, CSSProperties } from 'react'
4 import { Checkbox, Flex, FlexV, iconBtn } from './components'
5 -import { basename, closeDialog, formatBytes, formatPerc, hIcon, isMobile, newDialog, prefix, selectFiles, working } from './misc'
5 +import { basename, closeDialog, formatBytes, formatPerc, hIcon, isMobile, newDialog, prefix, selectFiles, working,
6 + HTTP_CONFLICT, HTTP_PAYLOAD_TOO_LARGE
7 +} from './misc'
8 import _ from 'lodash'
9 import { proxy, ref, subscribe, useSnapshot } from 'valtio'
10 import { alertDialog, confirmDialog, promptDialog } from './dialog'
@@ -280,7 +282,7 @@ async function startUpload(toUpload: ToUpload, to: string, resume=0) {
282 if (req?.readyState !== 4) return
283 const status = overrideStatus || req.status
284 closeLast?.()
283 - if (status && status !== 409) // 0 = user-aborted, 409 = skipped because existing
285 + if (status && status !== HTTP_CONFLICT) // 0 = user-aborted, HTTP_CONFLICT = skipped because existing
286 if (status >= 400)
287 error(status)
288 else
@@ -344,7 +346,7 @@ async function startUpload(toUpload: ToUpload, to: string, resume=0) {
346 function error(status: number) {
347 if (uploadState.errors++) return
348 const ERRORS = {
347 - 413: t`file too large`,
349 + [HTTP_PAYLOAD_TOO_LARGE]: t`file too large`,
350 }
351 const specifier = (ERRORS as any)[status]
352 const msg = t('failed_upload', toUpload, "Couldn't upload {name}") + prefix(': ', specifier)
@@ -423,7 +425,7 @@ async function createFolder() {
425 )))
426 }
427 catch(e: any) {
426 - await alertDialog(e.code === 409 ? t('folder_exists', "Folder with same name already exists") : e)
428 + await alertDialog(e.code === HTTP_CONFLICT ? t('folder_exists', "Folder with same name already exists") : e)
429 }
430 }
431
frontend/src/useFetchList.ts
+4 -4
@@ -7,7 +7,7 @@ import _ from 'lodash'
7 import { subscribeKey } from 'valtio/utils'
8 import { useIsMounted } from 'usehooks-ts'
9 import { alertDialog } from './dialog'
10 -import { HTTP_MESSAGES, LIST, xlate } from './misc'
10 +import { HTTP_MESSAGES, HTTP_METHOD_NOT_ALLOWED, HTTP_UNAUTHORIZED, LIST, xlate } from './misc'
11 import { t } from './i18n'
12 import { useLocation, useNavigate } from 'react-router-dom'
13
@@ -77,7 +77,7 @@ export default function useFetchList() {
77 if (!Array.isArray(entry)) continue // unexpected
78 const [op, par] = entry
79 const error = op === LIST.error && par
80 - if (error === 405) { // "method not allowed" happens when we try to directly access an unauthorized file, and we get a login prompt, and then get_file_list the file (because we didn't know it was file or folder)
80 + if (error === HTTP_METHOD_NOT_ALLOWED) { // "method not allowed" happens when we try to directly access an unauthorized file, and we get a login prompt, and then get_file_list the file (because we didn't know it was file or folder)
81 state.messageOnly = t('upload_starting', "Your download should now start")
82 window.location.reload() // reload will start the download, because now we got authenticated
83 continue
@@ -85,9 +85,9 @@ export default function useFetchList() {
85 if (error) {
86 state.stopSearch?.()
87 state.error = xlate(error, HTTP_MESSAGES)
88 - if (error === 401 && snap.username)
88 + if (error === HTTP_UNAUTHORIZED && snap.username)
89 alertDialog(t('wrong_account', { u: snap.username }, "Account {u} has no access, try another"), 'warning').then()
90 - state.loginRequired = error === 401
90 + state.loginRequired = error === HTTP_UNAUTHORIZED
91 lastReq.current = null
92 continue
93 }