diff --git a/src/webapp/features/cards/lib/dal.ts b/src/webapp/features/cards/lib/dal.ts index 84c4a2ac..0bb61898 100644 --- a/src/webapp/features/cards/lib/dal.ts +++ b/src/webapp/features/cards/lib/dal.ts @@ -1,4 +1,4 @@ -import { verifySessionOnClient } from '@/lib/auth/dal'; +import { verifySessionOnClient, logoutUser } from '@/lib/auth/dal'; import { createSembleClient } from '@/services/client.apiClient'; import { CardSortField, SortOrder, UrlType } from '@semble/types'; import { cache } from 'react'; @@ -51,14 +51,19 @@ export const addUrlToLibrary = cache( const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.addUrlToLibrary({ - url: url, - note: note, - collectionIds: collectionIds, - viaCardId: viaCardId, - }); - return response; + try { + const response = await client.addUrlToLibrary({ + url: url, + note: note, + collectionIds: collectionIds, + viaCardId: viaCardId, + }); + + return response; + } catch (error) { + await logoutUser(); + } }, ); @@ -96,12 +101,17 @@ export const removeCardFromCollection = cache( const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.removeCardFromCollection({ - cardId, - collectionIds, - }); - return response; + try { + const response = await client.removeCardFromCollection({ + cardId, + collectionIds, + }); + + return response; + } catch (error) { + await logoutUser(); + } }, ); @@ -109,9 +119,14 @@ export const removeCardFromLibrary = cache(async (cardId: string) => { const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.removeCardFromLibrary({ cardId }); - return response; + try { + const response = await client.removeCardFromLibrary({ cardId }); + + return response; + } catch (error) { + await logoutUser(); + } }); export const getLibrariesForCard = cache(async (cardId: string) => { diff --git a/src/webapp/features/collections/components/createCollectionDrawer/CreateCollectionDrawer.tsx b/src/webapp/features/collections/components/createCollectionDrawer/CreateCollectionDrawer.tsx index 630a7998..126557d0 100644 --- a/src/webapp/features/collections/components/createCollectionDrawer/CreateCollectionDrawer.tsx +++ b/src/webapp/features/collections/components/createCollectionDrawer/CreateCollectionDrawer.tsx @@ -44,12 +44,14 @@ export default function createCollectionDrawer(props: Props) { { onSuccess: (newCollection) => { props.onClose(); - props.onCreate && - props.onCreate({ - id: newCollection.collectionId, - name: form.getValues().name, - cardCount: 0, - }); + if (newCollection) { + props.onCreate && + props.onCreate({ + id: newCollection.collectionId, + name: form.getValues().name, + cardCount: 0, + }); + } }, onError: () => { notifications.show({ diff --git a/src/webapp/features/collections/lib/dal.ts b/src/webapp/features/collections/lib/dal.ts index f81ffa10..2790573a 100644 --- a/src/webapp/features/collections/lib/dal.ts +++ b/src/webapp/features/collections/lib/dal.ts @@ -1,4 +1,4 @@ -import { verifySessionOnClient } from '@/lib/auth/dal'; +import { logoutUser, verifySessionOnClient } from '@/lib/auth/dal'; import { createSembleClient } from '@/services/client.apiClient'; import { CardSortField, @@ -107,9 +107,14 @@ export const createCollection = cache( const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.createCollection(newCollection); - return response; + try { + const response = await client.createCollection(newCollection); + + return response; + } catch (error) { + await logoutUser(); + } }, ); @@ -117,9 +122,14 @@ export const deleteCollection = cache(async (id: string) => { const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.deleteCollection({ collectionId: id }); - return response; + try { + const response = await client.deleteCollection({ collectionId: id }); + + return response; + } catch (error) { + await logoutUser(); + } }); export const updateCollection = cache( @@ -132,9 +142,14 @@ export const updateCollection = cache( const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.updateCollection(collection); - return response; + try { + const response = await client.updateCollection(collection); + + return response; + } catch (error) { + await logoutUser(); + } }, ); diff --git a/src/webapp/features/collections/lib/mutations/useUpdateCollection.tsx b/src/webapp/features/collections/lib/mutations/useUpdateCollection.tsx index 33515ba5..a6859965 100644 --- a/src/webapp/features/collections/lib/mutations/useUpdateCollection.tsx +++ b/src/webapp/features/collections/lib/mutations/useUpdateCollection.tsx @@ -15,7 +15,7 @@ export default function useUpdateCollection() { return updateCollection(collection); }, - onSuccess: (variables) => { + onSuccess: (_data, variables) => { queryClient.invalidateQueries({ queryKey: collectionKeys.collection(variables.collectionId), }); diff --git a/src/webapp/features/notes/lib/dal.ts b/src/webapp/features/notes/lib/dal.ts index 99b814f2..8bb776cf 100644 --- a/src/webapp/features/notes/lib/dal.ts +++ b/src/webapp/features/notes/lib/dal.ts @@ -1,4 +1,4 @@ -import { verifySessionOnClient } from '@/lib/auth/dal'; +import { logoutUser, verifySessionOnClient } from '@/lib/auth/dal'; import { createSembleClient } from '@/services/client.apiClient'; import { cache } from 'react'; @@ -25,8 +25,13 @@ export const updateNoteCard = cache( const session = await verifySessionOnClient({ redirectOnFail: true }); if (!session) throw new Error('No session found'); const client = createSembleClient(); - const response = await client.updateNoteCard(note); - return response; + try { + const response = await client.updateNoteCard(note); + + return response; + } catch (error) { + await logoutUser(); + } }, ); diff --git a/src/webapp/features/notes/lib/mutations/useUpdateNote.tsx b/src/webapp/features/notes/lib/mutations/useUpdateNote.tsx index c25a9808..0731fe48 100644 --- a/src/webapp/features/notes/lib/mutations/useUpdateNote.tsx +++ b/src/webapp/features/notes/lib/mutations/useUpdateNote.tsx @@ -14,6 +14,7 @@ export default function useUpdateNote() { }, onSuccess: (data) => { + if (!data) return; queryClient.invalidateQueries({ queryKey: cardKeys.card(data.cardId) }); queryClient.invalidateQueries({ queryKey: cardKeys.infinite() }); queryClient.invalidateQueries({ diff --git a/src/webapp/lib/auth/dal.ts b/src/webapp/lib/auth/dal.ts index 5bad1e0c..0126be42 100644 --- a/src/webapp/lib/auth/dal.ts +++ b/src/webapp/lib/auth/dal.ts @@ -1,5 +1,6 @@ import type { GetProfileResponse } from '@/api-client/ApiClient'; import { cache } from 'react'; +import { ClientCookieAuthService } from '@/services/auth/CookieAuthService.client'; const appUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://127.0.0.1:4000'; @@ -48,3 +49,14 @@ export const verifySessionOnClient = cache( return refreshPromise; }, ); + +/** + * Logs out the current user by clearing tokens and redirecting to login + * Can be called from both client and server contexts + */ +export const logoutUser = async (): Promise => { + await ClientCookieAuthService.clearTokens(); + if (typeof window !== 'undefined') { + window.location.href = '/login'; + } +};