Hotfix
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useContext, useState, useRef, useEffect } from "react";
|
||||
import { FaTimes, FaSync, FaCheckCircle, FaExclamationCircle, FaHourglassHalf, FaMusic, FaCompactDisc, FaStepForward } from "react-icons/fa";
|
||||
import { QueueContext, type QueueItem, getStatus, getProgress, getCurrentTrackInfo, isActiveStatus, isTerminalStatus } from "@/contexts/queue-context";
|
||||
import { authApiClient } from "@/lib/api-client";
|
||||
import { useAuth } from "@/contexts/auth-context";
|
||||
|
||||
// Circular Progress Component
|
||||
const CircularProgress = ({
|
||||
@@ -452,9 +452,10 @@ const QueueItemCard = ({ item, cachedStatus }: { item: QueueItem, cachedStatus:
|
||||
|
||||
export const Queue = () => {
|
||||
const context = useContext(QueueContext);
|
||||
const { authEnabled, isAuthenticated } = useAuth();
|
||||
|
||||
// Check if user is authenticated
|
||||
const hasValidToken = authApiClient.getToken() !== null;
|
||||
// Check if user is authenticated (only relevant when auth is enabled)
|
||||
const isUserAuthenticated = !authEnabled || isAuthenticated;
|
||||
|
||||
const [startY, setStartY] = useState<number | null>(null);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
@@ -751,7 +752,7 @@ export const Queue = () => {
|
||||
};
|
||||
}, [isVisible]);
|
||||
|
||||
if (!context || !isVisible || !hasValidToken) return null;
|
||||
if (!context || !isVisible || !isUserAuthenticated) return null;
|
||||
|
||||
// Optimize: Calculate status once per item and reuse throughout render
|
||||
const itemsWithStatus = items.map(item => ({
|
||||
|
||||
@@ -335,6 +335,12 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
||||
return () => window.removeEventListener("storage", handleStorageChange);
|
||||
}, [initializeAuth]);
|
||||
|
||||
// Update API client when auth enabled state changes
|
||||
useEffect(() => {
|
||||
authApiClient.setAuthEnabled(authEnabled);
|
||||
console.log(`API client auth enabled state updated: ${authEnabled}`);
|
||||
}, [authEnabled]);
|
||||
|
||||
// Enhanced context value with new methods
|
||||
const contextValue = {
|
||||
// State
|
||||
|
||||
@@ -140,17 +140,27 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
if (sseConnection.current) return;
|
||||
|
||||
try {
|
||||
// Check if we have a valid token before connecting
|
||||
const token = authApiClient.getToken();
|
||||
if (!token) {
|
||||
console.warn("SSE: No auth token available, skipping connection");
|
||||
return;
|
||||
let eventSource: EventSource;
|
||||
|
||||
// Only check for auth token if auth is enabled
|
||||
if (authEnabled) {
|
||||
const token = authApiClient.getToken();
|
||||
if (!token) {
|
||||
console.warn("SSE: Auth is enabled but no auth token available, skipping connection");
|
||||
return;
|
||||
}
|
||||
|
||||
// Include token as query parameter for SSE authentication
|
||||
const sseUrl = `/api/prgs/stream?token=${encodeURIComponent(token)}`;
|
||||
eventSource = new EventSource(sseUrl);
|
||||
} else {
|
||||
// Auth is disabled, connect without token
|
||||
console.log("SSE: Auth disabled, connecting without token");
|
||||
const sseUrl = `/api/prgs/stream`;
|
||||
eventSource = new EventSource(sseUrl);
|
||||
}
|
||||
|
||||
// Include token as query parameter for SSE authentication
|
||||
const sseUrl = `/api/prgs/stream?token=${encodeURIComponent(token)}`;
|
||||
const eventSource = new EventSource(sseUrl);
|
||||
sseConnection.current = eventSource;
|
||||
|
||||
sseConnection.current = eventSource;
|
||||
|
||||
eventSource.onopen = () => {
|
||||
console.log("SSE connected successfully");
|
||||
@@ -364,14 +374,16 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
console.warn("SSE connection error:", error);
|
||||
}
|
||||
|
||||
// Check if this might be an auth error by testing if we still have a valid token
|
||||
const token = authApiClient.getToken();
|
||||
if (!token) {
|
||||
console.warn("SSE: Connection error and no auth token - stopping reconnection attempts");
|
||||
eventSource.close();
|
||||
sseConnection.current = null;
|
||||
stopHealthCheck();
|
||||
return;
|
||||
// Only check for auth errors if auth is enabled
|
||||
if (authEnabled) {
|
||||
const token = authApiClient.getToken();
|
||||
if (!token) {
|
||||
console.warn("SSE: Connection error and no auth token - stopping reconnection attempts");
|
||||
eventSource.close();
|
||||
sseConnection.current = null;
|
||||
stopHealthCheck();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
eventSource.close();
|
||||
@@ -410,7 +422,7 @@ export function QueueProvider({ children }: { children: ReactNode }) {
|
||||
toast.error("Failed to establish connection");
|
||||
}
|
||||
}
|
||||
}, [createQueueItemFromTask, scheduleRemoval, startHealthCheck]);
|
||||
}, [createQueueItemFromTask, scheduleRemoval, startHealthCheck, authEnabled]);
|
||||
|
||||
const disconnectSSE = useCallback(() => {
|
||||
if (sseConnection.current) {
|
||||
|
||||
@@ -15,6 +15,7 @@ class AuthApiClient {
|
||||
private apiClient: AxiosInstance;
|
||||
private token: string | null = null;
|
||||
private isCheckingToken: boolean = false;
|
||||
private authEnabled: boolean = false; // Track if auth is enabled
|
||||
|
||||
constructor() {
|
||||
this.apiClient = axios.create({
|
||||
@@ -31,7 +32,8 @@ class AuthApiClient {
|
||||
// Request interceptor to add auth token
|
||||
this.apiClient.interceptors.request.use(
|
||||
(config) => {
|
||||
if (this.token) {
|
||||
// Only add auth header if auth is enabled and we have a token
|
||||
if (this.authEnabled && this.token) {
|
||||
config.headers.Authorization = `Bearer ${this.token}`;
|
||||
}
|
||||
return config;
|
||||
@@ -55,29 +57,40 @@ class AuthApiClient {
|
||||
(error) => {
|
||||
// Handle authentication errors
|
||||
if (error.response?.status === 401) {
|
||||
// Only clear token for auth-related endpoints
|
||||
const requestUrl = error.config?.url || "";
|
||||
const isAuthEndpoint = requestUrl.includes("/auth/") || requestUrl.endsWith("/auth");
|
||||
|
||||
if (isAuthEndpoint) {
|
||||
// Clear invalid token only for auth endpoints
|
||||
this.clearToken();
|
||||
// Only process auth errors if auth is enabled
|
||||
if (this.authEnabled) {
|
||||
// Only clear token for auth-related endpoints
|
||||
const requestUrl = error.config?.url || "";
|
||||
const isAuthEndpoint = requestUrl.includes("/auth/") || requestUrl.endsWith("/auth");
|
||||
|
||||
// Only show auth error if auth is enabled and not during initial token check
|
||||
if (error.response?.data?.auth_enabled && !this.isCheckingToken) {
|
||||
toast.error("Session Expired", {
|
||||
description: "Please log in again to continue.",
|
||||
});
|
||||
if (isAuthEndpoint) {
|
||||
// Clear invalid token only for auth endpoints
|
||||
this.clearToken();
|
||||
|
||||
// Only show auth error if not during initial token check
|
||||
if (!this.isCheckingToken) {
|
||||
toast.error("Session Expired", {
|
||||
description: "Please log in again to continue.",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// For non-auth endpoints, just log the 401 but don't clear token
|
||||
// The token might still be valid for auth endpoints
|
||||
console.log(`401 error on non-auth endpoint: ${requestUrl}`);
|
||||
}
|
||||
} else {
|
||||
// For non-auth endpoints, just log the 401 but don't clear token
|
||||
// The token might still be valid for auth endpoints
|
||||
console.log(`401 error on non-auth endpoint: ${requestUrl}`);
|
||||
// Auth is disabled, 401 errors are expected for auth endpoints
|
||||
console.log("401 error received but auth is disabled - this is expected");
|
||||
}
|
||||
} else if (error.response?.status === 403) {
|
||||
toast.error("Access Denied", {
|
||||
description: "You don't have permission to perform this action.",
|
||||
});
|
||||
// Only show access denied errors if auth is enabled
|
||||
if (this.authEnabled) {
|
||||
toast.error("Access Denied", {
|
||||
description: "You don't have permission to perform this action.",
|
||||
});
|
||||
} else {
|
||||
console.log("403 error received but auth is disabled - this may be expected");
|
||||
}
|
||||
} else if (error.code === "ECONNABORTED") {
|
||||
toast.error("Request Timed Out", {
|
||||
description: "The server did not respond in time. Please try again later.",
|
||||
@@ -342,6 +355,15 @@ class AuthApiClient {
|
||||
return `/api/auth/sso/login/${provider}`;
|
||||
}
|
||||
|
||||
// Method to set auth enabled state (to be called by AuthProvider)
|
||||
setAuthEnabled(enabled: boolean) {
|
||||
this.authEnabled = enabled;
|
||||
}
|
||||
|
||||
getAuthEnabled(): boolean {
|
||||
return this.authEnabled;
|
||||
}
|
||||
|
||||
// Expose the underlying axios instance for other API calls
|
||||
get client() {
|
||||
return this.apiClient;
|
||||
|
||||
Reference in New Issue
Block a user