diff --git a/src/renderer/api/controller.ts b/src/renderer/api/controller.ts index 2629d6b7..4e3aa85f 100644 --- a/src/renderer/api/controller.ts +++ b/src/renderer/api/controller.ts @@ -43,8 +43,9 @@ import type { TopSongListResponse, UpdatePlaylistResponse, UserListResponse, + AuthenticationResponse, } from '/@/renderer/api/types'; -import { ServerListItem } from '/@/renderer/types'; +import { ServerType } from '/@/renderer/types'; import { DeletePlaylistResponse } from './types'; import { ndController } from '/@/renderer/api/navidrome/navidrome-controller'; import { ssController } from '/@/renderer/api/subsonic/subsonic-controller'; @@ -52,6 +53,10 @@ import { jfController } from '/@/renderer/api/jellyfin/jellyfin-controller'; export type ControllerEndpoint = Partial<{ addToPlaylist: (args: AddToPlaylistArgs) => Promise; + authenticate: ( + url: string, + body: { password: string; username: string }, + ) => Promise; clearPlaylist: () => void; createFavorite: (args: FavoriteArgs) => Promise; createPlaylist: (args: CreatePlaylistArgs) => Promise; @@ -92,6 +97,7 @@ type ApiController = { const endpoints: ApiController = { jellyfin: { addToPlaylist: jfController.addToPlaylist, + authenticate: jfController.authenticate, clearPlaylist: undefined, createFavorite: jfController.createFavorite, createPlaylist: jfController.createPlaylist, @@ -124,6 +130,7 @@ const endpoints: ApiController = { }, navidrome: { addToPlaylist: ndController.addToPlaylist, + authenticate: ndController.authenticate, clearPlaylist: undefined, createFavorite: ssController.createFavorite, createPlaylist: ndController.createPlaylist, @@ -155,6 +162,7 @@ const endpoints: ApiController = { updatePlaylist: ndController.updatePlaylist, }, subsonic: { + authenticate: ssController.authenticate, clearPlaylist: undefined, createFavorite: ssController.createFavorite, createPlaylist: undefined, @@ -185,8 +193,8 @@ const endpoints: ApiController = { }, }; -const apiController = (endpoint: keyof ControllerEndpoint, server?: ServerListItem | null) => { - const serverType = server?.type || useAuthStore.getState().currentServer?.type; +const apiController = (endpoint: keyof ControllerEndpoint, type?: ServerType) => { + const serverType = type || useAuthStore.getState().currentServer?.type; if (!serverType) { toast.error({ message: 'No server selected', title: 'Unable to route request' }); @@ -206,6 +214,14 @@ const apiController = (endpoint: keyof ControllerEndpoint, server?: ServerListIt return endpoints[serverType][endpoint]; }; +const authenticate = async ( + url: string, + body: { legacy?: boolean; password: string; username: string }, + type: ServerType, +) => { + return (apiController('authenticate', type) as ControllerEndpoint['authenticate'])?.(url, body); +}; + const getAlbumList = async (args: AlbumListArgs) => { return (apiController('getAlbumList') as ControllerEndpoint['getAlbumList'])?.(args); }; @@ -300,6 +316,7 @@ const scrobble = async (args: ScrobbleArgs) => { export const controller = { addToPlaylist, + authenticate, createFavorite, createPlaylist, deleteFavorite, diff --git a/src/renderer/features/servers/components/add-server-form.tsx b/src/renderer/features/servers/components/add-server-form.tsx index 80e9a481..33a61f94 100644 --- a/src/renderer/features/servers/components/add-server-form.tsx +++ b/src/renderer/features/servers/components/add-server-form.tsx @@ -5,12 +5,10 @@ import { useForm } from '@mantine/form'; import { useFocusTrap } from '@mantine/hooks'; import { closeAllModals } from '@mantine/modals'; import { nanoid } from 'nanoid/non-secure'; -import { jellyfinApi } from '/@/renderer/api/jellyfin.api'; -import { navidromeApi } from '/@/renderer/api/navidrome.api'; -import { subsonicApi } from '/@/renderer/api/subsonic.api'; import { AuthenticationResponse } from '/@/renderer/api/types'; import { useAuthStore, useAuthStoreActions } from '/@/renderer/store'; import { ServerType } from '/@/renderer/types'; +import { api } from '/@/renderer/api'; const SERVER_TYPES = [ { label: 'Jellyfin', value: ServerType.JELLYFIN }, @@ -18,12 +16,6 @@ const SERVER_TYPES = [ // { label: 'Subsonic', value: ServerType.SUBSONIC }, ]; -const AUTH_FUNCTIONS = { - [ServerType.JELLYFIN]: jellyfinApi.authenticate, - [ServerType.NAVIDROME]: navidromeApi.authenticate, - [ServerType.SUBSONIC]: subsonicApi.authenticate, -}; - interface AddServerFormProps { onCancel: () => void; } @@ -48,7 +40,7 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => { const isSubmitDisabled = !form.values.name || !form.values.url || !form.values.username; const handleSubmit = form.onSubmit(async (values) => { - const authFunction = AUTH_FUNCTIONS[values.type]; + const authFunction = api.controller.authenticate; if (!authFunction) { return toast.error({ message: 'Selected server type is invalid' }); @@ -56,11 +48,19 @@ export const AddServerForm = ({ onCancel }: AddServerFormProps) => { try { setIsLoading(true); - const data: AuthenticationResponse = await authFunction(values.url, { - legacy: values.legacyAuth, - password: values.password, - username: values.username, - }); + const data: AuthenticationResponse | undefined = await authFunction( + values.url, + { + legacy: values.legacyAuth, + password: values.password, + username: values.username, + }, + values.type, + ); + + if (!data) { + return toast.error({ message: 'Authentication failed' }); + } const serverItem = { credential: data.credential, diff --git a/src/renderer/features/servers/components/edit-server-form.tsx b/src/renderer/features/servers/components/edit-server-form.tsx index ef6d9354..d0d8712c 100644 --- a/src/renderer/features/servers/components/edit-server-form.tsx +++ b/src/renderer/features/servers/components/edit-server-form.tsx @@ -5,12 +5,10 @@ import { useForm } from '@mantine/form'; import { useFocusTrap } from '@mantine/hooks'; import { closeAllModals } from '@mantine/modals'; import { RiInformationLine } from 'react-icons/ri'; -import { jellyfinApi } from '/@/renderer/api/jellyfin.api'; -import { navidromeApi } from '/@/renderer/api/navidrome.api'; -import { subsonicApi } from '/@/renderer/api/subsonic.api'; import { AuthenticationResponse } from '/@/renderer/api/types'; import { useAuthStoreActions } from '/@/renderer/store'; import { ServerListItem, ServerType } from '/@/renderer/types'; +import { api } from '/@/renderer/api'; interface EditServerFormProps { isUpdate?: boolean; @@ -18,12 +16,6 @@ interface EditServerFormProps { server: ServerListItem; } -const AUTH_FUNCTIONS = { - [ServerType.JELLYFIN]: jellyfinApi.authenticate, - [ServerType.NAVIDROME]: navidromeApi.authenticate, - [ServerType.SUBSONIC]: subsonicApi.authenticate, -}; - const ModifiedFieldIndicator = () => { return ( @@ -53,7 +45,7 @@ export const EditServerForm = ({ isUpdate, server, onCancel }: EditServerFormPro const isSubsonic = form.values.type === ServerType.SUBSONIC; const handleSubmit = form.onSubmit(async (values) => { - const authFunction = AUTH_FUNCTIONS[values.type]; + const authFunction = api.controller.authenticate; if (!authFunction) { return toast.error({ message: 'Selected server type is invalid' }); @@ -61,11 +53,19 @@ export const EditServerForm = ({ isUpdate, server, onCancel }: EditServerFormPro try { setIsLoading(true); - const data: AuthenticationResponse = await authFunction(values.url, { - legacy: values.legacyAuth, - password: values.password, - username: values.username, - }); + const data: AuthenticationResponse | undefined = await authFunction( + values.url, + { + legacy: values.legacyAuth, + password: values.password, + username: values.username, + }, + values.type, + ); + + if (!data) { + return toast.error({ message: 'Authentication failed' }); + } const serverItem = { credential: data.credential,