Files
donetick/src/queries/UserQueries.jsx
Mo Tarbin 8edd3774d2 Support Refresh token and improve authentication and security.
Refactor authentication handling and API client integration

- Updated UserProfileAvatar to use 'access_token' instead of 'ca_token' for logout.
- Removed SSEProvider from Contexts and adjusted related imports.
- Introduced useAuth hook for centralized authentication logic, including login, logout, and token management.
- Refactored useSSE to utilize the new useAuth hook for token validation.
- Updated UserQueries to check for token validity using the new method.
- Deleted AuthenticationService as its functionality is now handled by useAuth.
- Created a new ApiClient utility for handling API requests and token management.
- Updated various components and views to use the new ApiClient for API interactions.
- Removed TokenManager and migrated its functionality to the new ApiClient.
- Adjusted LoginView and related components to utilize the new authentication flow.
- Cleaned up unused variables and improved code consistency across components.
2025-12-25 22:54:39 -05:00

124 lines
3.1 KiB
JavaScript

import { useQuery, useQueryClient } from '@tanstack/react-query'
import {
GetAllCircleMembers,
GetAllUsers,
GetChildUsers,
GetDeviceTokens,
GetUserProfile,
} from '../utils/Fetcher'
// Helper to check if we have a valid token
const isTokenValid = () => {
const token = localStorage.getItem('token')
if (!token) return false
const expiry = localStorage.getItem('token_expiry')
if (!expiry) return true // No expiry set, assume valid
return new Date() < new Date(expiry)
}
export const useAllUsers = () => {
return useQuery({
queryKey: ['allUsers'],
queryFn: GetAllUsers,
})
}
export const useCircleMembers = () => {
const queryClient = useQueryClient()
const { data, error, isLoading } = useQuery({
queryKey: ['allCircleMembers'],
queryFn: GetAllCircleMembers,
})
const handleRefetch = () => {
queryClient.invalidateQueries(['allCircleMembers'])
}
return { data, error, isLoading, handleRefetch }
}
export const useUserProfile = () => {
const queryClient = useQueryClient()
const { data, error, isLoading } = useQuery({
queryKey: ['userProfile'],
queryFn: async () => {
if (!isTokenValid()) {
throw new Error('Invalid or expired token, cannot fetch user profile')
}
const resp = await GetUserProfile()
const result = await resp.json()
// if we got 403 then user probably deleted their account and token is still valid. navigate to login
if (resp.status === 403) {
localStorage.removeItem('access_token')
localStorage.removeItem('ca_expiration')
window.location.href = '/login'
throw new Error('User account deleted or access forbidden')
}
return result.res // Return the actual user profile data
},
staleTime: 30 * 60 * 1000, // 30 minutes in milliseconds
gcTime: 30 * 60 * 1000, // 30 minutes in milliseconds
})
return {
data,
error,
isLoading,
refetch: () => queryClient.invalidateQueries(['userProfile']),
}
}
export const useDeviceTokens = () => {
const queryClient = useQueryClient()
const { data, error, isLoading } = useQuery({
queryKey: ['deviceTokens'],
queryFn: async () => {
if (!isTokenValid()) {
return null
}
const resp = await GetDeviceTokens(true) // Only get active devices
const result = await resp.json()
return result.res || []
},
staleTime: 0, // Always fetch fresh data
gcTime: 10 * 60 * 1000, // 10 minutes
})
return {
data,
error,
isLoading,
refetch: () => queryClient.invalidateQueries(['deviceTokens']),
}
}
export const useChildUsers = () => {
const queryClient = useQueryClient()
const { data, error, isLoading } = useQuery({
queryKey: ['childUsers'],
queryFn: async () => {
if (!isTokenValid()) {
return null
}
const resp = await GetChildUsers()
const result = await resp.json()
return result.res || []
},
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
})
return {
data,
error,
isLoading,
refetch: () => queryClient.invalidateQueries(['childUsers']),
}
}