diff --git a/firestore.rules b/firestore.rules index 8df862e..8ef700e 100644 --- a/firestore.rules +++ b/firestore.rules @@ -79,7 +79,9 @@ service cloud.firestore { // --- Signals Collection --- match /signals/{signalId} { - allow get, list: if isSignedIn() && (resource.data.userId == request.auth.uid || isDbAdmin()); + allow get: if isSignedIn() && (resource.data.userId == request.auth.uid || isDbAdmin()); + allow list: if isSignedIn() && resource.data.userId == request.auth.uid; + allow list: if isDbAdmin(); function isValidSignal(data) { return data.keys().hasAll(['userId', 'pair', 'timeframe', 'decision', 'score', 'timestamp', 'result']) diff --git a/src/App.tsx b/src/App.tsx index e36a495..acffcc2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,7 +16,7 @@ import { NotificationManager } from './components/NotificationManager'; import { TrendingUp, ShieldAlert, Ghost, Mail, Lock, UserPlus, LogIn, Loader2, ArrowLeft, User as UserIcon, Eye, EyeOff } from 'lucide-react'; import { motion, AnimatePresence } from 'motion/react'; import { onAuthStateChanged, signInWithEmailAndPassword, createUserWithEmailAndPassword, updateProfile, signOut, sendEmailVerification, sendPasswordResetEmail, User, setPersistence, browserLocalPersistence, browserSessionPersistence } from 'firebase/auth'; -import { doc, setDoc, getDoc } from 'firebase/firestore'; +import { doc, setDoc, getDoc, updateDoc } from 'firebase/firestore'; import { auth, db, handleFirestoreError, OperationType } from './lib/firebase'; export default function App() { @@ -68,6 +68,21 @@ export default function App() { if (userSnap.exists()) { data = { ...data, ...userSnap.data() }; + + // Force admin rights for root email + if (currentUser.email === "fxbrosinvestments00@gmail.com") { + data.isAdmin = true; + data.isApproved = true; + + if (userSnap.data().isAdmin !== true || userSnap.data().isApproved !== true) { + try { + await updateDoc(userRef, { isAdmin: true, isApproved: true }); + } catch (e) { + console.error("Failed to update root admin privileges:", e); + } + } + } + if (!data.isApproved && !data.isAdmin) { await signOut(auth); setAuthError('Sua conta foi criada. Aguarde aprovação manual do administrador.'); diff --git a/src/components/AnalysisView.tsx b/src/components/AnalysisView.tsx index 825daf0..a476f88 100644 --- a/src/components/AnalysisView.tsx +++ b/src/components/AnalysisView.tsx @@ -66,13 +66,14 @@ export const AnalysisView: React.FC<{ userData?: any }> = ({ userData }) => { try { let downloadUrl = null; if (auth.currentUser) { - const fileRef = ref(storage, `files/${Date.now()}_${file.name}`); + const fileRef = ref(storage, `scans/${auth.currentUser.uid}/${Date.now()}_${file.name}`); await uploadBytes(fileRef, file); downloadUrl = await getDownloadURL(fileRef); } const base64 = preview.split(',')[1]; const analysis = await analyzeForexChart(base64, undefined, mode); + analysis.score = Math.round(analysis.score); setResult(analysis); if (auth.currentUser) { diff --git a/storage.rules b/storage.rules index 87f8625..7d56f8a 100644 --- a/storage.rules +++ b/storage.rules @@ -14,5 +14,13 @@ service firebase.storage { && request.resource.contentType.matches('image/.*'); allow delete: if isSignedIn() && (request.auth.uid == userId || isDbAdmin()); } + + match /scans/{userId}/{fileName} { + allow read: if isSignedIn() && (request.auth.uid == userId || isDbAdmin()); + allow create, update: if isSignedIn() && (request.auth.uid == userId || isDbAdmin()) + && request.resource.size < 5 * 1024 * 1024 // 5MB limit + && request.resource.contentType.matches('image/.*'); + allow delete: if isSignedIn() && (request.auth.uid == userId || isDbAdmin()); + } } }