feat: Enhance security and user management

Refines Firestore and Storage rules to enforce stricter access controls for signals and user-uploaded files. Updates user data handling to ensure root administrator privileges are correctly applied and enforced. Organizes uploaded scan files into user-specific directories within storage.
This commit is contained in:
desartstudio95
2026-05-06 23:48:03 +02:00
parent 3fe6dd4671
commit 175723475a
4 changed files with 29 additions and 3 deletions
+3 -1
View File
@@ -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'])
+16 -1
View File
@@ -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.');
+2 -1
View File
@@ -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) {
+8
View File
@@ -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());
}
}
}