@samitouri / QOSami-HFS / commits / 34070227

fix: admin/accounts: wrong message displayed in case of expired account

Massimo Melina committed Apr 15, 2025 at 22:36 UTC 34070227a9936997e04d24e5b11bff4ba2f91b8d
5 files changed +17 -8
admin/src/AccountForm.ts
+5 -2
@@ -69,8 +69,11 @@ export default function AccountForm({ account, done, groups, addToBar, reload }:
69 getError: (x, { values }) => (x||'') !== (values.password||'') && "Enter same password" },
70
71 { k: 'disabled', comp: BoolField, fromField: x=>!x, toField: x=>!x, label: "Enabled", xs: 12, sm: 6, lg: 8,
72 - helperText: !values.disabled && values.canLogin === false ? h(Box, { color: 'warning.main', component: 'span' }, "Login is prevented because all of its groups are disabled")
73 - : "Login is prevented if account is disabled, or all its groups are disabled" },
72 + helperText: values.disabled || values.canLogin !== false ? "Login is prevented if account is disabled, or all its groups are disabled"
73 + : h(Box, { color: 'warning.main', component: 'span' },
74 + new Date(account.expire!) < new Date() ? "Login is prevented because account is expired" // use account instead of values, so to use the value currently applied
75 + : "Login is prevented because all of its groups are disabled")
76 + },
77 { k: 'ignore_limits', comp: BoolField, xs: 12, sm: 6, lg: 4,
78 helperText: values.ignore_limits ? "Speed limits don't apply to this account" : "Speed limits apply to this account" },
79
admin/src/AccountsPage.ts
+2 -2
@@ -6,7 +6,7 @@ import { Alert, Box, Card, CardContent, Grid, List, ListItem, ListItemText, Typo
6 import {
7 AccountTree, ChevronRight, Close, Delete, DoNotDisturb, ExpandMore, Group, MilitaryTech, Person, PersonAdd, Schedule
8 } from '@mui/icons-material'
9 -import { newDialog, with_, md } from './misc'
9 +import { newDialog, with_, md, Jsonify } from './misc'
10 import { Btn, Flex, IconBtn, iconTooltip, reloadBtn, useBreakpoint, useToggleButton } from './mui'
11 import { TreeItem, TreeView } from '@mui/x-tree-view'
12 import MenuButton from './MenuButton'
@@ -17,7 +17,7 @@ import { state, useSnapState } from './state'
17 import { importAccountsCsv } from './importAccountsCsv'
18 import apiAccounts from '../../src/api.accounts'
19
20 -export type Account = ReturnType<typeof apiAccounts.get_accounts>['list'][0]
20 +export type Account = Jsonify<ReturnType<typeof apiAccounts.get_accounts>['list'][0]>
21
22 export default function AccountsPage() {
23 const { username, accountsAsTree } = useSnapState()
shared/api.ts
+4 -3
@@ -2,8 +2,9 @@
2
3 import _ from 'lodash';
4 import { useCallback, useEffect, useMemo, useRef } from 'react';
5 -import { Callback, Dict, Falsy, getPrefixUrl, pendingPromise, useStateMounted, wait,
6 - buildUrlQueryString, } from '.'
5 +import {
6 + Callback, Dict, Falsy, getPrefixUrl, pendingPromise, useStateMounted, wait, buildUrlQueryString, Jsonify,
7 +} from '.'
8 import { BetterEventEmitter } from '../src/events'
9
10 export const API_URL = '/~/api/'
@@ -84,7 +85,7 @@ export class ApiError extends Error {
85
86 export type UseApi<T=unknown> = ReturnType<typeof useApi<T>>
87 export function useApi<T=any>(cmd: string | Falsy, params?: object, options: ApiCallOptions={}) {
87 - const [data, setData, getData] = useStateMounted<Awaited<ReturnType<typeof apiCall<T>>> | undefined>(undefined)
88 + const [data, setData, getData] = useStateMounted<Jsonify<Awaited<ReturnType<typeof apiCall<T>>>> | undefined>(undefined)
89 const [error, setError] = useStateMounted<Error | undefined>(undefined)
90 const [forcer, setForcer] = useStateMounted(0)
91 const [loading, setLoading, getLoading] = useStateMounted<undefined | ReturnType<typeof apiCall>>(undefined)
src/cross.ts
+5
@@ -59,6 +59,11 @@ export type Who = typeof WHO_ANYONE
59 | WhoObject
60 | AccountList // use false instead of empty array to keep the type boolean-able
61 export interface WhoObject { this?: Who, children?: Who }
62 +export type Jsonify<T> = T extends string | number | boolean | null | undefined ? T : // undefined is necessary to preserve union types, like number|undefined
63 + T extends Date ? string :
64 + T extends (infer U)[] ? Jsonify<U>[] :
65 + T extends object ? { [K in keyof T]: Jsonify<T[K]> } :
66 + never
67
68 export const defaultPerms: Required<VfsPerms> = {
69 can_see: 'can_read',
src/middlewares.ts
+1 -1
@@ -17,7 +17,7 @@ import { app } from './index'
17 import events from './events'
18
19 const forceHttps = defineConfig('force_https', true)
20 -const ignoreProxies = defineConfig('ignore_proxies', false)
20 +defineConfig('ignore_proxies', false)
21 const allowAuthorizationHeader = defineConfig('authorization_header', true)
22 export const sessionDuration = defineConfig('session_duration', Number(process.env.SESSION_DURATION) || DAY/1000,
23 v => v * 1000)