zmiany w obsłudze kluczy api i zabezpieczeń

This commit is contained in:
Arek Bykowski
2026-02-15 18:11:54 +01:00
parent 48b7f2b3bb
commit 78a34498d0
5 changed files with 87 additions and 254 deletions

View File

@@ -87,7 +87,6 @@ const PlaceAutocompleteInput: React.FC<PlaceAutocompleteInputProps> = ({ value,
// --- MAIN COMPONENT ---
interface StepDetailsProps {
data: WizardState;
// Update Type Definition to allow functional updates
updateData: (updates: Partial<WizardState> | ((prev: WizardState) => Partial<WizardState>)) => void;
onGenerate: () => void;
isGenerating: boolean;
@@ -96,41 +95,23 @@ interface StepDetailsProps {
const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate, isGenerating }) => {
const fileInputRef = useRef<HTMLInputElement>(null);
const [error, setError] = useState<string | null>(null);
// Specific Error State
const [mapError, setMapError] = useState<{title: string, msg: string} | null>(null);
const [scriptLoaded, setScriptLoaded] = useState(false);
// --- HARDCODED FALLBACK KEY ---
const AUTO_PASTE_KEY = 'AIzaSyAq9IgZswt5j7GGfH2s-ESenHmfvWFCFCg';
// STRICT MODE: Use VITE_GOOGLE_MAPS_KEY
const getEffectiveKey = () => {
if (data.tripData?.googleMapsKey) return data.tripData.googleMapsKey;
const viteKey = getEnvVar('VITE_GOOGLE_MAPS_KEY');
if (viteKey) return viteKey;
const procKey = getEnvVar('GOOGLE_MAPS_KEY');
if (procKey) return procKey;
return AUTO_PASTE_KEY;
return getEnvVar('VITE_GOOGLE_MAPS_KEY');
};
const effectiveKey = getEffectiveKey();
const isEnvKeyMissing = !getEnvVar('GOOGLE_MAPS_KEY') &&
!getEnvVar('VITE_GOOGLE_MAPS_KEY') &&
data.tripData?.googleMapsKey !== AUTO_PASTE_KEY;
// Warning if no key is found at all
const isKeyMissing = !effectiveKey;
// --- GOOGLE MAPS LOADING ---
const loadMapsScript = (apiKey: string) => {
if (!apiKey) {
setMapError({
title: "Brak klucza API",
msg: "System nie mógł znaleźć klucza. Skontaktuj się z administratorem."
});
return;
}
if (!apiKey) return;
if ((window as any).google?.maps?.places) {
setScriptLoaded(true);
@@ -169,7 +150,7 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
useEffect(() => {
if (data.eventType === 'trip') {
(window as any).gm_authFailure = () => {
setMapError({ title: "Klucz odrzucony przez Google", msg: "Podany klucz jest niepoprawny." });
setMapError({ title: "Klucz odrzucony przez Google", msg: "Podany klucz jest niepoprawny lub domena nie jest autoryzowana." });
setScriptLoaded(false);
};
if (effectiveKey) loadMapsScript(effectiveKey);
@@ -186,17 +167,12 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
endPoint: { place: '', description: '' },
stops: [{ id: crypto.randomUUID(), place: '', description: '' }],
travelMode: null,
googleMapsKey: AUTO_PASTE_KEY
googleMapsKey: '' // Don't auto-fill undefined keys
}
});
}
else if (!data.tripData.googleMapsKey) {
updateData(prev => ({
tripData: { ...prev.tripData!, googleMapsKey: AUTO_PASTE_KEY }
}));
}
}
}, [data.eventType, updateData]); // Removed data.tripData dependency to avoid loops, handled by logic
}, [data.eventType, updateData]);
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const newFiles = Array.from(e.target.files || []);
@@ -214,7 +190,7 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
updateData(prev => ({ files: prev.files.filter(f => f.id !== id) }));
};
// --- TRIP DATA HELPERS (UPDATED TO USE FUNCTIONAL STATE UPDATES) ---
// --- TRIP DATA HELPERS ---
const updateApiKey = (val: string) => {
updateData(prev => ({
tripData: prev.tripData ? { ...prev.tripData, googleMapsKey: val } : prev.tripData
@@ -299,15 +275,15 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
{data.eventType === 'trip' && data.tripData && (
<div className="bg-gray-50 border border-gray-200 rounded-xl p-6 space-y-6">
{/* Fallback Input */}
{(!data.tripData.googleMapsKey && isEnvKeyMissing) && (
{/* Manual Input if Env key is missing */}
{isKeyMissing && !data.tripData.googleMapsKey && (
<div className="bg-yellow-50 p-4 rounded-md border border-yellow-200 mb-2">
<div className="flex items-start gap-3">
<AlertCircle className="text-yellow-600 mt-0.5" size={20} />
<div className="flex-1">
<h4 className="font-bold text-yellow-800 text-sm">Nie wykryto klucza w .env</h4>
<h4 className="font-bold text-yellow-800 text-sm">Brak klucza w konfiguracji (VITE_GOOGLE_MAPS_KEY)</h4>
<p className="text-xs text-yellow-700 mt-1 mb-2">
System automatycznie wklei klucz zapasowy. Jeśli to nie nastąpiło, wklej go poniżej.
Wklej klucz ręcznie poniżej, aby mapy zadziałały.
</p>
<input
type="text"
@@ -344,7 +320,6 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
</div>
</div>
{/* BIG TRAVEL MODE SELECTOR */}
<div className="grid grid-cols-2 gap-4 w-full">
<button
onClick={() => setTravelMode('DRIVING')}
@@ -370,7 +345,6 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
</button>
</div>
{/* Validation Message if missing */}
{!data.tripData.travelMode && (
<p className="text-center text-xs text-red-500 font-bold animate-pulse">
* Wybór rodzaju trasy jest wymagany
@@ -378,8 +352,6 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
)}
<div className="space-y-4 pt-2">
{/* START POINT */}
<div className="flex gap-3 items-start">
<div className="flex-1 grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="relative">
@@ -404,11 +376,9 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
placeholder="Opis startu (np. Zbiórka o 6:00)"
/>
</div>
{/* Placeholder for alignment */}
<div className="w-[42px]"></div>
</div>
{/* STOPS */}
{data.tripData.stops.map((stop, index) => (
<div key={stop.id} className="flex gap-3 items-start group">
<div className="flex-1 grid grid-cols-1 md:grid-cols-2 gap-3">
@@ -454,7 +424,6 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
</button>
</div>
{/* END POINT */}
<div className="flex gap-3 items-start">
<div className="flex-1 grid grid-cols-1 md:grid-cols-2 gap-3">
<div className="relative">
@@ -479,15 +448,13 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
placeholder="Opis końca (np. Nareszcie piwo)"
/>
</div>
{/* Placeholder for alignment */}
<div className="w-[42px]"></div>
</div>
</div>
</div>
)}
{/* STANDARDOWE POLA */}
{/* Standard Fields */}
<div className="space-y-6">
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">Tytuł wydarzenia</label>
@@ -511,7 +478,6 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
/>
</div>
{/* File Upload */}
<div>
<label className="block text-sm font-bold text-gray-700 mb-2">Materiały pomocnicze (Max 3)</label>
<div
@@ -535,7 +501,6 @@ const StepDetails: React.FC<StepDetailsProps> = ({ data, updateData, onGenerate,
{error && <p className="text-red-500 text-sm mt-2">{error}</p>}
{/* File List */}
{data.files.length > 0 && (
<div className="mt-4 grid grid-cols-1 gap-3">
{data.files.map((file) => (