Flutter'da Firebase Entegrasyonu: Auth, Firestore ve Storage

Firebase, Flutter'ın en yaygın kullanılan backend çözümüdür. Authentication, gerçek zamanlı veritabanı, dosya depolama ve push bildirim gibi hazır servisleriyle arka uç geliştirme ihtiyacını büyük ölçüde azaltır.

Kurulum

# FlutterFire CLI ile yapılandırma
dart pub global activate flutterfire_cli
flutterfire configure --project=benim-projem

# pubspec.yaml
# firebase_core: ^3.3.0
# firebase_auth: ^5.1.4
# cloud_firestore: ^5.2.1
# firebase_storage: ^12.1.3
// main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const UygulamaWidget());
}

Firebase Authentication

class AuthServis {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  // Kullanıcı oturumu akışı
  Stream<User?> get kullanicıAkisi => _auth.authStateChanges();

  // E-posta ile kayıt
  Future<UserCredential> kayitOl({
    required String email,
    required String sifre,
    required String isim,
  }) async {
    final credential = await _auth.createUserWithEmailAndPassword(
      email: email,
      password: sifre,
    );
    await credential.user?.updateDisplayName(isim);
    await credential.user?.sendEmailVerification();
    return credential;
  }

  // E-posta ile giriş
  Future<UserCredential> girisYap(String email, String sifre) =>
      _auth.signInWithEmailAndPassword(email: email, password: sifre);

  // Google ile giriş
  Future<UserCredential> googleIleGiris() async {
    final googleUser = await GoogleSignIn().signIn();
    final googleAuth = await googleUser!.authentication;
    final credential = GoogleAuthProvider.credential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    return _auth.signInWithCredential(credential);
  }

  // Şifre sıfırlama
  Future<void> sifreSifirla(String email) =>
      _auth.sendPasswordResetEmail(email: email);

  Future<void> cikisYap() => _auth.signOut();
  User? get mevcutKullanici => _auth.currentUser;
}

Auth ile Korunan Rotalar

class AuthGateway extends StatelessWidget {
  const AuthGateway({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Scaffold(body: Center(child: CircularProgressIndicator()));
        }
        return snapshot.hasData ? const AnaSayfa() : const GirisSayfasi();
      },
    );
  }
}

Cloud Firestore CRUD

class GonderiDepo {
  final _koleksiyon = FirebaseFirestore.instance.collection("gonderiler");

  // Oluştur
  Future<DocumentReference> gonderiOlustur(Gonderi gonderi) =>
      _koleksiyon.add(gonderi.toJson());

  // Oku - tek döküman
  Future<Gonderi?> gonderiGetir(String id) async {
    final doc = await _koleksiyon.doc(id).get();
    return doc.exists ? Gonderi.fromJson(doc.data()!, doc.id) : null;
  }

  // Gerçek zamanlı liste dinle
  Stream<List<Gonderi>> gonderileriDinle(String kullaniciId) =>
      _koleksiyon
          .where("kullaniciId", isEqualTo: kullaniciId)
          .orderBy("olusturulmaZamani", descending: true)
          .limit(20)
          .snapshots()
          .map((snap) => snap.docs
              .map((d) => Gonderi.fromJson(d.data(), d.id))
              .toList());

  // Güncelle
  Future<void> gonderiGuncelle(String id, Map<String, dynamic> guncellemeler) =>
      _koleksiyon.doc(id).update({
        ...guncellemeler,
        "guncellenmeZamani": FieldValue.serverTimestamp(),
      });

  // Sil
  Future<void> gonderiSil(String id) => _koleksiyon.doc(id).delete();

  // Toplu işlem
  Future<void> topluGuncelle(List<String> idler, Map<String, dynamic> degerler) async {
    final batch = FirebaseFirestore.instance.batch();
    for (final id in idler) {
      batch.update(_koleksiyon.doc(id), degerler);
    }
    await batch.commit();
  }
}

Firebase Storage — Dosya Yükleme

class DepolamaServis {
  final _storage = FirebaseStorage.instance;

  Future<String> resimYukle({
    required String kullaniciId,
    required Uint8List bytes,
    required String uzanti,
  }) async {
    final ref = _storage.ref("profil//avatar.");

    final gorev = ref.putData(
      bytes,
      SettableMetadata(contentType: "image/"),
    );

    // İlerleme takibi
    gorev.snapshotEvents.listen((snapshot) {
      final yuzde = snapshot.bytesTransferred / snapshot.totalBytes * 100;
      print("Yükleniyor: %");
    });

    await gorev;
    return ref.getDownloadURL();
  }

  Future<void> dosyaSil(String url) async {
    final ref = _storage.refFromURL(url);
    await ref.delete();
  }
}

// image_picker ile kullanım
Future<void> profilResmiGuncelle() async {
  final picker = ImagePicker();
  final secilen = await picker.pickImage(
    source: ImageSource.gallery,
    maxWidth: 512,
    maxHeight: 512,
    imageQuality: 85,
  );

  if (secilen == null) return;

  final bytes = await secilen.readAsBytes();
  final uzanti = secilen.path.split(".").last;
  final url = await DepolamaServis().resimYukle(
    kullaniciId: AuthServis().mevcutKullanici!.uid,
    bytes: bytes,
    uzanti: uzanti,
  );

  await FirebaseAuth.instance.currentUser?.updatePhotoURL(url);
}

Firestore Güvenlik Kuralları

// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // Kullanıcı kendi verisine erişebilir
    match /kullanicilar/{userId} {
      allow read: if request.auth != null;
      allow write: if request.auth.uid == userId;
    }

    // Gönderiler: herkes okuyabilir, sadece sahip düzenleyebilir
    match /gonderiler/{gonderiId} {
      allow read: if true;
      allow create: if request.auth != null
          && request.resource.data.kullaniciId == request.auth.uid;
      allow update, delete: if request.auth.uid == resource.data.kullaniciId;
    }
  }
}

Offline Destek

// Firestore offline önbelleği etkinleştir
FirebaseFirestore.instance.settings = const Settings(
  persistenceEnabled: true,
  cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
);

Sonuç

Firebase, Flutter uygulamalarına hızla backend kapasitesi kazandırır. Authentication ile güvenli giriş, Firestore ile gerçek zamanlı veri ve Storage ile dosya yönetimi üçlüsü çoğu uygulama için yeterlidir. Güvenlik kurallarını ihmal etmeyin — production'da her koleksiyon için kural tanımlamak zorunludur.