diff --git a/admin-frontend/src/api/auth.ts b/admin-frontend/src/api/auth.ts index a4b2c14..7189347 100644 --- a/admin-frontend/src/api/auth.ts +++ b/admin-frontend/src/api/auth.ts @@ -48,8 +48,12 @@ export const authApi = { }, me: async (): Promise => { - const { data } = await apiClient.get('/api/v1/auth/me') - return data + const response = await apiClient.get('/api/v1/auth/me') + console.log('🔍 Raw /me API response:', response) + console.log('🔍 Response data:', response.data) + console.log('🔍 Response data type:', typeof response.data) + console.log('🔍 Response data keys:', response.data ? Object.keys(response.data) : 'no keys') + return response.data }, changePassword: async ( diff --git a/admin-frontend/src/api/client.ts b/admin-frontend/src/api/client.ts index a5ad15e..ccbe58d 100644 --- a/admin-frontend/src/api/client.ts +++ b/admin-frontend/src/api/client.ts @@ -3,7 +3,11 @@ import axios from 'axios' // Get API base URL from environment variable or use default // The .env file should contain: VITE_API_URL=http://127.0.0.1:8000 // Alternatively, Vite proxy can be used (configured in vite.config.ts) by setting VITE_API_URL to empty string -const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:8000' +// When VITE_API_URL is empty/undefined, use relative path to work with HTTPS proxy +const envApiUrl = import.meta.env.VITE_API_URL +const API_BASE_URL = envApiUrl && envApiUrl.trim() !== '' + ? envApiUrl + : '' // Use relative path when empty - works with proxy and HTTPS export const apiClient = axios.create({ baseURL: API_BASE_URL, diff --git a/admin-frontend/src/api/jobs.ts b/admin-frontend/src/api/jobs.ts index 1a9d9c6..51bb8c5 100644 --- a/admin-frontend/src/api/jobs.ts +++ b/admin-frontend/src/api/jobs.ts @@ -27,8 +27,11 @@ export const jobsApi = { }, streamJobProgress: (jobId: string): EventSource => { - // EventSource needs absolute URL - use VITE_API_URL or fallback to direct backend URL - const baseURL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:8000' + // EventSource needs absolute URL - use VITE_API_URL or construct from current origin + const envApiUrl = import.meta.env.VITE_API_URL + const baseURL = envApiUrl && envApiUrl.trim() !== '' + ? envApiUrl + : window.location.origin // Use current origin when empty - works with proxy and HTTPS return new EventSource(`${baseURL}/api/v1/jobs/stream/${jobId}`) }, diff --git a/admin-frontend/src/api/photos.ts b/admin-frontend/src/api/photos.ts index 3f52719..3d1aab4 100644 --- a/admin-frontend/src/api/photos.ts +++ b/admin-frontend/src/api/photos.ts @@ -70,8 +70,11 @@ export const photosApi = { }, streamJobProgress: (jobId: string): EventSource => { - // EventSource needs absolute URL - use VITE_API_URL or fallback to direct backend URL - const baseURL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:8000' + // EventSource needs absolute URL - use VITE_API_URL or construct from current origin + const envApiUrl = import.meta.env.VITE_API_URL + const baseURL = envApiUrl && envApiUrl.trim() !== '' + ? envApiUrl + : window.location.origin // Use current origin when empty - works with proxy and HTTPS return new EventSource(`${baseURL}/api/v1/jobs/stream/${jobId}`) }, diff --git a/admin-frontend/src/api/videos.ts b/admin-frontend/src/api/videos.ts index b0e77a7..45fdc73 100644 --- a/admin-frontend/src/api/videos.ts +++ b/admin-frontend/src/api/videos.ts @@ -108,12 +108,18 @@ export const videosApi = { }, getThumbnailUrl: (videoId: number): string => { - const baseURL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:8000' + const envApiUrl = import.meta.env.VITE_API_URL + const baseURL = envApiUrl && envApiUrl.trim() !== '' + ? envApiUrl + : '' // Use relative path when empty - works with proxy and HTTPS return `${baseURL}/api/v1/videos/${videoId}/thumbnail` }, getVideoUrl: (videoId: number): string => { - const baseURL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:8000' + const envApiUrl = import.meta.env.VITE_API_URL + const baseURL = envApiUrl && envApiUrl.trim() !== '' + ? envApiUrl + : '' // Use relative path when empty - works with proxy and HTTPS return `${baseURL}/api/v1/videos/${videoId}/video` }, } diff --git a/admin-frontend/src/context/AuthContext.tsx b/admin-frontend/src/context/AuthContext.tsx index dce4063..3db1c02 100644 --- a/admin-frontend/src/context/AuthContext.tsx +++ b/admin-frontend/src/context/AuthContext.tsx @@ -38,6 +38,12 @@ export function AuthProvider({ children }: { children: ReactNode }) { authApi .me() .then((user) => { + console.log('🔍 Auth /me response:', { + username: user.username, + is_admin: user.is_admin, + role: user.role, + permissions: user.permissions + }) setAuthState({ isAuthenticated: true, username: user.username, @@ -81,6 +87,12 @@ export function AuthProvider({ children }: { children: ReactNode }) { localStorage.setItem('access_token', tokens.access_token) localStorage.setItem('refresh_token', tokens.refresh_token) const user = await authApi.me() + console.log('🔍 Login /me response:', { + username: user.username, + is_admin: user.is_admin, + role: user.role, + permissions: user.permissions + }) const passwordChangeRequired = tokens.password_change_required || false setAuthState({ isAuthenticated: true, @@ -133,7 +145,13 @@ export function AuthProvider({ children }: { children: ReactNode }) { if (authState.isAdmin) { return true } - return Boolean(authState.permissions[featureKey]) + const hasPerm = Boolean(authState.permissions[featureKey]) + console.log(`🔍 hasPermission(${featureKey}):`, { + isAdmin: authState.isAdmin, + hasPerm, + permissions: authState.permissions + }) + return hasPerm }, [authState.isAdmin, authState.permissions] ) diff --git a/admin-frontend/src/pages/Identify.tsx b/admin-frontend/src/pages/Identify.tsx index 68090b3..1adc2ec 100644 --- a/admin-frontend/src/pages/Identify.tsx +++ b/admin-frontend/src/pages/Identify.tsx @@ -604,7 +604,8 @@ export default function Identify() { const preloadImages = () => { const preloadUrls: string[] = [] - const baseUrl = apiClient.defaults.baseURL || 'http://127.0.0.1:8000' + // Use relative path when baseURL is empty (works with proxy and HTTPS) + const baseUrl = apiClient.defaults.baseURL || '' // Preload next face if (currentIdx + 1 < faces.length) { diff --git a/admin-frontend/src/pages/ReportedPhotos.tsx b/admin-frontend/src/pages/ReportedPhotos.tsx index 9a0831a..49910ee 100644 --- a/admin-frontend/src/pages/ReportedPhotos.tsx +++ b/admin-frontend/src/pages/ReportedPhotos.tsx @@ -41,7 +41,8 @@ export default function ReportedPhotos() { // Create direct backend URLs for images (only for non-video photos) const newImageUrls: Record = {} - const baseURL = apiClient.defaults.baseURL || 'http://10.0.10.121:8000' + // Use relative path when baseURL is empty (works with proxy and HTTPS) + const baseURL = apiClient.defaults.baseURL || '' response.items.forEach((reported) => { if (reported.photo_id && reported.photo_media_type !== 'video') { // Use direct backend URL - the backend endpoint doesn't require auth for images