dodanie hasla i poprawki

This commit is contained in:
Arek Bykowski
2026-02-15 17:27:19 +01:00
parent 27a3c6024f
commit bd62be6a5d
3 changed files with 186 additions and 7 deletions

BIN
.DS_Store vendored

Binary file not shown.

191
App.tsx
View File

@@ -7,10 +7,31 @@ import StepEventType from './components/StepEventType';
import StepToneGoal from './components/StepToneGoal';
import StepDetails from './components/StepDetails';
import StepResult from './components/StepResult';
import { ChevronLeft, ExternalLink, Sparkles, User } from 'lucide-react';
import { ChevronLeft, ExternalLink, Sparkles, User, Lock, ArrowRight, AlertCircle, Bug } from 'lucide-react';
import { generateStoryContent } from './services/geminiService';
const STORAGE_KEY = 'gpx-storyteller-state-v6'; // Incremented version for structure change
const AUTH_KEY = 'promptstory-auth-token';
// --- PASSWORD CONFIGURATION ---
// 1. Try fetching from Vite standard (import.meta.env)
// @ts-ignore
const VITE_ENV_PASS = import.meta.env && import.meta.env.VITE_APP_PASSWORD ? import.meta.env.VITE_APP_PASSWORD : '';
// 2. Try fetching from Process env (sometimes used in other build tools)
// @ts-ignore
const PROCESS_ENV_PASS = (typeof process !== 'undefined' && process.env && process.env.VITE_APP_PASSWORD) ? process.env.VITE_APP_PASSWORD : '';
// 3. Fallback (Hardcoded safety net)
// W tym środowisku (AI Studio/Web Preview) restart serwera jest trudny.
// Ustawiamy hasło "na sztywno" jako zapas, żeby działało od razu.
const FALLBACK_PASS = 'Prometeusz';
// Decision Logic
const ENV_PASSWORD = VITE_ENV_PASS || PROCESS_ENV_PASS;
const APP_PASSWORD = ENV_PASSWORD || FALLBACK_PASS;
const IS_USING_FALLBACK = !ENV_PASSWORD;
const INITIAL_STATE: WizardState = {
step: Step.CONTEXT,
@@ -38,7 +59,131 @@ const INITIAL_STATE: WizardState = {
}
};
// --- LOGIN SCREEN COMPONENT ---
const LoginScreen: React.FC<{ onLogin: (success: boolean) => void }> = ({ onLogin }) => {
const [input, setInput] = useState('');
const [error, setError] = useState(false);
const [showDebug, setShowDebug] = useState(false);
// DEBUGGING: Log to console on mount
useEffect(() => {
console.group("--- DEBUG PASSWORD SYSTEM ---");
console.log("1. Detected VITE_ENV:", VITE_ENV_PASS ? "****" : "(empty)");
console.log("2. Detected PROCESS_ENV:", PROCESS_ENV_PASS ? "****" : "(empty)");
console.log("3. Final Password Source:", IS_USING_FALLBACK ? "FALLBACK (Hardcoded)" : ".ENV FILE");
console.log("4. Active Password Length:", APP_PASSWORD.length);
console.groupEnd();
}, []);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Trim input to avoid accidental spaces from copy-paste
if (input.trim() === APP_PASSWORD) {
onLogin(true);
} else {
console.log(`Failed Login. Input: "${input}" vs Expected: "${APP_PASSWORD}"`);
setError(true);
setInput('');
}
};
return (
<div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center p-4">
<div className="bg-white p-8 rounded-xl shadow-lg border border-gray-100 max-w-md w-full text-center space-y-6 animate-fade-in relative">
{/* Debug Toggle (Hidden in corner) */}
<button
onClick={() => setShowDebug(!showDebug)}
className="absolute top-2 right-2 text-gray-200 hover:text-gray-400 p-2"
title="Pokaż informacje debugowania"
>
<Bug size={16} />
</button>
<div className="flex justify-center mb-2">
<div className="bg-[#EA4420]/10 p-4 rounded-full text-[#EA4420]">
<Lock size={32} />
</div>
</div>
<div>
<h2 className="text-2xl font-bold text-gray-900">Dostęp Chroniony</h2>
<p className="text-gray-500 mt-2">Wprowadź hasło, aby uzyskać dostęp do kreatora PromptStory.</p>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="relative">
<input
type="password"
value={input}
onChange={(e) => {
setInput(e.target.value);
setError(false);
}}
placeholder="Hasło..."
className={`w-full p-4 border rounded-lg outline-none transition-all font-medium text-center tracking-widest ${
error
? 'border-red-300 bg-red-50 focus:border-red-500'
: 'border-gray-200 focus:border-[#EA4420] focus:ring-1 focus:ring-[#EA4420]'
}`}
autoFocus
/>
</div>
{error && (
<div className="flex items-center justify-center gap-2 text-red-500 text-sm font-medium animate-pulse">
<AlertCircle size={16} />
<span>Nieprawidłowe hasło</span>
</div>
)}
<button
type="submit"
className="w-full bg-[#EA4420] text-white py-4 rounded-lg font-bold hover:bg-[#d63b1a] transition-colors flex items-center justify-center gap-2"
>
<span>Odblokuj</span>
<ArrowRight size={20} />
</button>
</form>
{/* DEBUG PANEL */}
{showDebug && (
<div className="bg-gray-800 text-left text-green-400 p-4 rounded-md text-xs font-mono mt-4 overflow-hidden">
<p className="font-bold border-b border-gray-600 mb-2 pb-1 text-white">DEBUG STATUS:</p>
<div className="grid grid-cols-2 gap-x-4 gap-y-1 mt-2">
<span className="text-gray-400">SOURCE:</span>
<span className={IS_USING_FALLBACK ? "text-yellow-400 font-bold" : "text-green-400 font-bold"}>
{IS_USING_FALLBACK ? "FALLBACK (Code)" : ".ENV FILE"}
</span>
<span className="text-gray-400">ACTIVE PASS:</span>
<span>{APP_PASSWORD.substring(0, 4)}... (len: {APP_PASSWORD.length})</span>
</div>
{IS_USING_FALLBACK && (
<div className="mt-3 text-yellow-500 border-t border-gray-600 pt-2">
<p>System używa hasła awaryjnego zdefiniowanego w kodzie, ponieważ nie może odświeżyć pliku .env bez restartu.</p>
<p className="mt-1 font-bold text-white">Twoje hasło powinno teraz działać.</p>
</div>
)}
</div>
)}
<p className="text-xs text-gray-300 pt-4">
PromptStory v1.0 Private Instance
</p>
</div>
</div>
);
};
const App: React.FC = () => {
// Auth State
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [isAuthChecking, setIsAuthChecking] = useState(true);
// App State
const [data, setData] = useState<WizardState>(INITIAL_STATE);
const [generatedContent, setGeneratedContent] = useState<GeneratedContent | null>(null);
const [isGenerating, setIsGenerating] = useState(false);
@@ -49,7 +194,29 @@ const App: React.FC = () => {
const [logoError, setLogoError] = useState(false);
const [avatarError, setAvatarError] = useState(false);
// Persistence Logic
// 1. Check Auth on Mount
useEffect(() => {
const storedAuth = localStorage.getItem(AUTH_KEY);
if (storedAuth === 'true') {
setIsAuthenticated(true);
}
setIsAuthChecking(false);
}, []);
const handleLogin = (success: boolean) => {
if (success) {
localStorage.setItem(AUTH_KEY, 'true');
setIsAuthenticated(true);
}
};
const handleLogout = () => {
localStorage.removeItem(AUTH_KEY);
setIsAuthenticated(false);
resetApp();
};
// 2. Load Data Persistence Logic
useEffect(() => {
const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
@@ -154,7 +321,13 @@ const App: React.FC = () => {
window.location.reload();
};
if (!isLoaded) return null;
// --- RENDER LOGIC ---
if (isAuthChecking || !isLoaded) return null; // Loading state
if (!isAuthenticated) {
return <LoginScreen onLogin={handleLogin} />;
}
// Step Labels for Progress Bar (Order Changed)
const stepsLabels = ['Kontekst', 'Typ', 'Platforma', 'Vibe & Cel', 'Szczegóły'];
@@ -179,9 +352,15 @@ const App: React.FC = () => {
)}
<h1 className="text-xl font-bold tracking-tight text-gray-900">PromptStory</h1>
</div>
<button onClick={resetApp} className="text-xs font-medium text-gray-400 hover:text-[#EA4420] transition-colors uppercase tracking-wide">
Resetuj
</button>
<div className="flex items-center gap-4">
<button onClick={resetApp} className="text-xs font-medium text-gray-400 hover:text-[#EA4420] transition-colors uppercase tracking-wide">
Resetuj
</button>
<button onClick={handleLogout} className="text-xs font-medium text-gray-400 hover:text-red-500 transition-colors uppercase tracking-wide">
Wyloguj
</button>
</div>
</div>
</header>

View File

@@ -12,4 +12,4 @@ root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
);