diff --git a/index.html b/index.html index 8449f5f..8889a1c 100644 --- a/index.html +++ b/index.html @@ -74,6 +74,27 @@ let storedAccount = localStorage.getItem("account") || "default"; let userInfo = JSON.parse(localStorage.getItem("userInfo") || "null"); + // If we have an API key but no userInfo, fetch it from the server + if (storedApiKey && !userInfo) { + fetch(`${apiBaseUrl}/userinfo`, { + headers: { "Authorization": `Bearer ${storedApiKey}` } + }) + .then(response => response.json()) + .then(userData => { + userInfo = {email: userData.email || "Utilisateur connecté"}; + localStorage.setItem("userInfo", JSON.stringify(userInfo)); + renderLoginSection(); + }) + .catch(e => { + console.error("Error fetching user info:", e); + // If we can't fetch user info, proceed with rendering + renderLoginSection(); + }); + } else { + // Render the login section normally + renderLoginSection(); + } + // Handle the static "abc" key case - removed for security /* if (storedApiKey === "abc" && !userInfo) { @@ -101,41 +122,56 @@ localStorage.setItem("apikey", accessToken); storedApiKey = accessToken; - // Get user info from the token - try { - // First, try to parse as JWT - const tokenParts = accessToken.split('.'); - let userData = {}; - - if (tokenParts.length === 3) { - // Standard JWT format - const payload = tokenParts[1]; - if (payload) { - // Add padding if needed - const paddedPayload = payload.padEnd(payload.length + (4 - payload.length % 4) % 4, '='); - const decodedPayload = atob(paddedPayload); - userData = JSON.parse(decodedPayload); - } - } else { - // Non-JWT token, treat as opaque token - console.log("Non-JWT token received, using default user info"); - userData = {email: "utilisateur@" + window.location.hostname}; - } - + // Get user info from the userinfo endpoint + fetch(`${apiBaseUrl}/userinfo`, { + headers: { "Authorization": `Bearer ${accessToken}` } + }) + .then(response => response.json()) + .then(userData => { userInfo = {email: userData.email || "Utilisateur connecté"}; localStorage.setItem("userInfo", JSON.stringify(userInfo)); - } catch (e) { - console.error("Error decoding token:", e); - // Fallback to a generic user object - userInfo = {email: "Utilisateur connecté"}; - localStorage.setItem("userInfo", JSON.stringify(userInfo)); - } + + // Update UI + renderLoginSection(); + }) + .catch(e => { + console.error("Error fetching user info:", e); + // Fallback to parsing token as JWT + try { + // First, try to parse as JWT + const tokenParts = accessToken.split('.'); + let userData = {}; + + if (tokenParts.length === 3) { + // Standard JWT format + const payload = tokenParts[1]; + if (payload) { + // Add padding if needed + const paddedPayload = payload.padEnd(payload.length + (4 - payload.length % 4) % 4, '='); + const decodedPayload = atob(paddedPayload); + userData = JSON.parse(decodedPayload); + } + } else { + // Non-JWT token, treat as opaque token + console.log("Non-JWT token received, using default user info"); + userData = {email: "utilisateur@" + window.location.hostname}; + } + + userInfo = {email: userData.email || "Utilisateur connecté"}; + localStorage.setItem("userInfo", JSON.stringify(userInfo)); + } catch (parseError) { + console.error("Error decoding token:", parseError); + // Fallback to a generic user object + userInfo = {email: "Utilisateur connecté"}; + localStorage.setItem("userInfo", JSON.stringify(userInfo)); + } + + // Update UI + renderLoginSection(); + }); // Remove token from URL window.history.replaceState({}, document.title, "/"); - - // Update UI - renderLoginSection(); } function renderLoginSection() { @@ -153,9 +189,8 @@ eventFilters.style.display = "block"; updateAccountOptions(); - if (storedApiKey) { - fetchEvents(storedApiKey, storedAccount); - } + // Don't automatically fetch events on page load + // Wait for user to explicitly select an account or click fetch } else { // User is not logged in connectedUser.style.display = "none"; @@ -216,15 +251,35 @@ } accountSelect.innerHTML = ''; + + // If no accounts are available, add a default option + if (accounts.length === 0) { + const option = document.createElement("option"); + option.value = "default"; + option.textContent = "Default"; + accountSelect.appendChild(option); + return; + } + + // Add all available accounts accounts.forEach(account => { const option = document.createElement("option"); option.value = account.name; option.textContent = account.label; - if (account.name === storedAccount) { - option.selected = true; - } accountSelect.appendChild(option); }); + + // Select the stored account if it exists, otherwise select the first account + let accountToSelect = storedAccount; + if (!accounts.some(account => account.name === storedAccount)) { + accountToSelect = accounts[0].name; + // Update stored account + storedAccount = accountToSelect; + localStorage.setItem("account", accountToSelect); + } + + // Set the selected account in the dropdown + accountSelect.value = accountToSelect; }) .catch(error => { console.error("Erreur lors du chargement des comptes:", error); @@ -268,12 +323,28 @@ return; } if (!response.ok) { - return response.json().then(errorData => { - console.error("Schedule error response:", errorData); - throw new Error(`HTTP error! status: ${response.status}, message: ${errorData.detail || 'Unknown error'}`); + // Try to parse error response as JSON, but handle plain text as well + return response.text().then(errorText => { + let errorMessage = 'Unknown error'; + try { + const errorData = JSON.parse(errorText); + errorMessage = errorData.detail || errorData.message || errorText; + } catch (e) { + // If parsing fails, use the raw text + errorMessage = errorText || 'Unknown error'; + } + console.error("Schedule error response:", errorText); + throw new Error(`HTTP error! status: ${response.status}, message: ${errorMessage}`); }); } - return response.json(); + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (e) { + console.error("Invalid JSON response:", text); + throw new Error("Le serveur a renvoyé une réponse invalide. Veuillez réessayer."); + } + }); }) .then(data => { if (data) { diff --git a/myice/myice.py b/myice/myice.py index 4691b58..c838220 100755 --- a/myice/myice.py +++ b/myice/myice.py @@ -635,7 +635,16 @@ def refresh_data(): return r.json() except json.JSONDecodeError: # If direct parsing fails, try with sanitization - return json.loads(sanitize_json_response(r.text)) + sanitized = sanitize_json_response(r.text) + try: + return json.loads(sanitized) + except json.JSONDecodeError: + # If sanitization also fails, log the raw response for debugging + print( + f"Failed to parse response as JSON. Raw response: {r.text[:500]}..." + ) + # Return an empty dict to avoid breaking the API + return {} @app.command("mobile-login") diff --git a/myice/webapi.py b/myice/webapi.py index 5dfa24d..350de8e 100644 --- a/myice/webapi.py +++ b/myice/webapi.py @@ -276,7 +276,10 @@ async def schedule( config_section=account ) except Exception as e: - raise HTTPException(400, detail=f"Configuration error: {str(e)}") + raise HTTPException( + 400, + detail=f"Configuration error: {str(e)}. Available accounts: isaac, leonard", + ) try: if existing_token: @@ -296,6 +299,9 @@ async def schedule( return [] except Exception as e: print(f"Error fetching schedule: {e}") + import traceback + + traceback.print_exc() # Return empty array instead of throwing an error return []