fixing oauth redirect issues

# Conflicts:
#	app/proprietary/src/main/java/stirling/software/proprietary/security/filter/UserAuthenticationFilter.java

# Conflicts:
#	app/core/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java
This commit is contained in:
Dario Ghunney Ware
2025-10-31 13:10:00 +00:00
committed by DarioGii
parent b4f9ed031e
commit e6c49d1737
6 changed files with 118 additions and 137 deletions

View File

@@ -1,10 +1,5 @@
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
// Helper to get JWT from localStorage for Authorization header
function getAuthHeaders(): HeadersInit {
const token = localStorage.getItem('stirling_jwt');
return token ? { 'Authorization': `Bearer ${token}` } : {};
}
import apiClient from '@app/services/apiClient';
export interface AppConfig {
baseUrl?: string;
@@ -65,41 +60,27 @@ export const AppConfigProvider: React.FC<{ children: ReactNode }> = ({ children
return;
}
// Don't fetch config if we're on the login page and don't have JWT
const isLoginPage = window.location.pathname.includes('/login');
const hasJwt = !!localStorage.getItem('stirling_jwt');
if (isLoginPage && !hasJwt) {
console.debug('[AppConfig] On login page without JWT - using default config');
setConfig({ enableLogin: true });
setLoading(false);
return;
}
try {
setLoading(true);
setError(null);
const response = await fetch('/api/v1/config/app-config', {
headers: getAuthHeaders(),
});
// apiClient automatically adds JWT header if available via interceptors
const response = await apiClient.get<AppConfig>('/api/v1/config/app-config');
const data = response.data;
if (!response.ok) {
// On 401 (not authenticated), use default config with login enabled
if (response.status === 401) {
console.debug('[AppConfig] 401 error - using default config (login enabled)');
setConfig({ enableLogin: true });
setLoading(false);
return;
}
throw new Error(`Failed to fetch config: ${response.status} ${response.statusText}`);
}
const data: AppConfig = await response.json();
console.debug('[AppConfig] Config fetched successfully:', data);
setConfig(data);
setFetchCount(prev => prev + 1);
} catch (err) {
} catch (err: any) {
// On 401 (not authenticated), use default config with login enabled
// This allows the app to work even without authentication
if (err.response?.status === 401) {
console.debug('[AppConfig] 401 error - using default config (login enabled)');
setConfig({ enableLogin: true });
setLoading(false);
return;
}
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
setError(errorMessage);
console.error('[AppConfig] Failed to fetch app config:', err);

View File

@@ -1,16 +1,10 @@
import { useState, useEffect } from 'react';
import { useRequestHeaders } from '@app/hooks/useRequestHeaders';
import apiClient from '@app/services/apiClient';
// Track globally fetched endpoint sets to prevent duplicate fetches across components
const globalFetchedSets = new Set<string>();
const globalEndpointCache: Record<string, boolean> = {};
// Helper to get JWT from localStorage for Authorization header
function getAuthHeaders(): HeadersInit {
const token = localStorage.getItem('stirling_jwt');
return token ? { 'Authorization': `Bearer ${token}` } : {};
}
/**
* Hook to check if a specific endpoint is enabled
* This wraps the context for single endpoint checks
@@ -24,7 +18,6 @@ export function useEndpointEnabled(endpoint: string): {
const [enabled, setEnabled] = useState<boolean | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const _headers = useRequestHeaders();
const fetchEndpointStatus = async () => {
if (!endpoint) {
@@ -37,15 +30,8 @@ export function useEndpointEnabled(endpoint: string): {
setLoading(true);
setError(null);
const response = await fetch(`/api/v1/config/endpoint-enabled?endpoint=${encodeURIComponent(endpoint)}`, {
headers: getAuthHeaders(),
});
if (!response.ok) {
throw new Error(`Failed to check endpoint: ${response.status} ${response.statusText}`);
}
const isEnabled: boolean = await response.json();
const response = await apiClient.get<boolean>(`/api/v1/config/endpoint-enabled?endpoint=${encodeURIComponent(endpoint)}`);
const isEnabled = response.data;
setEnabled(isEnabled);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
@@ -80,8 +66,6 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
const [endpointStatus, setEndpointStatus] = useState<Record<string, boolean>>({});
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [lastFetchedEndpoints, setLastFetchedEndpoints] = useState<string>('');
const _headers = useRequestHeaders();
const fetchAllEndpointStatuses = async (force = false) => {
const endpointsKey = [...endpoints].sort().join(',');
@@ -139,27 +123,8 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
// Use batch API for efficiency - only fetch new endpoints
const endpointsParam = newEndpoints.join(',');
const response = await fetch(`/api/v1/config/endpoints-enabled?endpoints=${encodeURIComponent(endpointsParam)}`, {
headers: getAuthHeaders(),
});
if (!response.ok) {
// On 401 (auth error), use optimistic fallback instead of disabling
if (response.status === 401) {
console.warn('[useEndpointConfig] 401 error - using optimistic fallback');
const optimisticStatus = endpoints.reduce((acc, endpoint) => {
acc[endpoint] = true;
globalEndpointCache[endpoint] = true; // Cache the optimistic value
return acc;
}, {} as Record<string, boolean>);
setEndpointStatus(optimisticStatus);
setLoading(false);
return;
}
throw new Error(`Failed to check endpoints: ${response.status} ${response.statusText}`);
}
const statusMap: Record<string, boolean> = await response.json();
const response = await apiClient.get<Record<string, boolean>>(`/api/v1/config/endpoints-enabled?endpoints=${encodeURIComponent(endpointsParam)}`);
const statusMap = response.data;
// Update global cache with new results
Object.assign(globalEndpointCache, statusMap);
@@ -172,8 +137,20 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
setEndpointStatus(fullStatus);
globalFetchedSets.add(endpointsKey);
setLastFetchedEndpoints(endpointsKey);
} catch (err) {
} catch (err: any) {
// On 401 (auth error), use optimistic fallback instead of disabling
if (err.response?.status === 401) {
console.warn('[useEndpointConfig] 401 error - using optimistic fallback');
const optimisticStatus = endpoints.reduce((acc, endpoint) => {
acc[endpoint] = true;
globalEndpointCache[endpoint] = true; // Cache the optimistic value
return acc;
}, {} as Record<string, boolean>);
setEndpointStatus(optimisticStatus);
setLoading(false);
return;
}
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
setError(errorMessage);
console.error('[EndpointConfig] Failed to check multiple endpoints:', err);
@@ -200,7 +177,6 @@ export function useMultipleEndpointsEnabled(endpoints: string[]): {
// Clear the global cache to allow refetch with JWT
globalFetchedSets.clear();
Object.keys(globalEndpointCache).forEach(key => delete globalEndpointCache[key]);
setLastFetchedEndpoints('');
fetchAllEndpointStatuses(true);
};