handle Navidrome login loop error

This commit is contained in:
Kendall Garner 2025-06-26 21:14:20 -07:00
parent bdc372636b
commit fb584b35a9
No known key found for this signature in database
GPG key ID: 9355F387FE765C94
3 changed files with 44 additions and 23 deletions

View file

@ -62,7 +62,8 @@ const ActionRequiredRoute = () => {
</Group> </Group>
<Stack mt="2rem"> <Stack mt="2rem">
{canReturnHome && <Navigate to={AppRoute.HOME} />} {canReturnHome && <Navigate to={AppRoute.HOME} />}
{!displayedCheck && ( {/* This should be displayed if a credential is required */}
{isCredentialRequired && (
<Group <Group
justify="center" justify="center"
wrap="nowrap" wrap="nowrap"

View file

@ -1,40 +1,57 @@
import isElectron from 'is-electron';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { api } from '/@/renderer/api'; import { api } from '/@/renderer/api';
import { useCurrentServer } from '/@/renderer/store'; import { useAuthStoreActions, useCurrentServer } from '/@/renderer/store';
import { toast } from '/@/shared/components/toast/toast'; import { toast } from '/@/shared/components/toast/toast';
import { SongListSort, SortOrder } from '/@/shared/types/domain-types'; import { SongListSort, SortOrder } from '/@/shared/types/domain-types';
import { AuthState, ServerListItem, ServerType } from '/@/shared/types/types'; import { AuthState, ServerListItem, ServerType } from '/@/shared/types/types';
const localSettings = isElectron() ? window.api.localSettings : null;
export const useServerAuthenticated = () => { export const useServerAuthenticated = () => {
const priorServerId = useRef<string | undefined>(undefined); const priorServerId = useRef<string | undefined>(undefined);
const server = useCurrentServer(); const server = useCurrentServer();
const [ready, setReady] = useState( const [ready, setReady] = useState(
server?.type === ServerType.NAVIDROME ? AuthState.LOADING : AuthState.VALID, server?.type === ServerType.NAVIDROME ? AuthState.VALID : AuthState.VALID,
); );
const authenticateNavidrome = useCallback(async (server: ServerListItem) => { const { updateServer } = useAuthStoreActions();
// This trick works because navidrome-api.ts will internally check for authentication
// failures and try to log in again (where available). So, all that's necessary is
// making one request first
try {
await api.controller.getSongList({
apiClientProps: { server },
query: {
limit: 1,
sortBy: SongListSort.NAME,
sortOrder: SortOrder.ASC,
startIndex: 0,
},
});
setReady(AuthState.VALID); const authenticateNavidrome = useCallback(
} catch (error) { async (server: ServerListItem) => {
toast.error({ message: (error as Error).message }); // This trick works because navidrome-api.ts will internally check for authentication
setReady(AuthState.INVALID); // failures and try to log in again (where available). So, all that's necessary is
} // making one request first
}, []); try {
await api.controller.getSongList({
apiClientProps: { server },
query: {
limit: 1,
sortBy: SongListSort.NAME,
sortOrder: SortOrder.ASC,
startIndex: 0,
},
});
setReady(AuthState.VALID);
} catch (error) {
// Clear server credentials (and saved password).
if (server.savePassword && localSettings) {
localSettings.passwordRemove(server.id);
}
server.credential = '';
updateServer(server.id, server);
toast.error({ message: (error as Error).message });
setReady(AuthState.INVALID);
}
},
[updateServer],
);
const debouncedAuth = debounce((server: ServerListItem) => { const debouncedAuth = debounce((server: ServerListItem) => {
authenticateNavidrome(server).catch(console.error); authenticateNavidrome(server).catch(console.error);

View file

@ -19,6 +19,8 @@ export const AppOutlet = () => {
const setFallback = useSetPlayerFallback(); const setFallback = useSetPlayerFallback();
const authState = useServerAuthenticated(); const authState = useServerAuthenticated();
console.log(authState);
const isActionsRequired = useMemo(() => { const isActionsRequired = useMemo(() => {
const isServerRequired = !currentServer; const isServerRequired = !currentServer;
@ -55,6 +57,7 @@ export const AppOutlet = () => {
} }
if (isActionsRequired || authState === AuthState.INVALID) { if (isActionsRequired || authState === AuthState.INVALID) {
console.log('required', isActionsRequired);
return ( return (
<Navigate <Navigate
replace replace