Flutter के लिए Firebase के बारे में जानें

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.

1. शुरू करने से पहले

इस कोडलैब में, आप Android और iOS के लिए Flutter मोबाइल ऐप बनाने के लिए Firebase की कुछ मूलभूत बातें सीखेंगे।

आवश्यक शर्तें

यह कोडलैब मानता है कि आप फ़्लटर से परिचित हैं, और आपने फ़्लटर एसडीके और एक संपादक स्थापित किया है।

आप क्या बनाएंगे

इस कोडलैब में आप फ़्लटर का उपयोग करके Android, iOS, वेब और macOS पर एक ईवेंट RSVP और गेस्टबुक चैट ऐप बनाएंगे। आप क्लाउड फायरस्टोर का उपयोग करके उपयोगकर्ताओं को फायरबेस प्रमाणीकरण और सिंक डेटा के साथ प्रमाणित करेंगे।

आपको किस चीज़ की ज़रूरत पड़ेगी

आप निम्न में से किसी भी डिवाइस का उपयोग करके इस कोडलैब को चला सकते हैं:

  • एक भौतिक उपकरण (एंड्रॉइड या आईओएस) आपके कंप्यूटर से जुड़ा है और डेवलपर मोड पर सेट है।
  • आईओएस सिम्युलेटर। ( Xcode उपकरण स्थापित करने की आवश्यकता है।)
  • एंड्रॉइड एमुलेटर। ( एंड्रॉइड स्टूडियो में सेटअप की आवश्यकता है।)

उपरोक्त के अलावा, आपको इसकी भी आवश्यकता होगी:

  • आपकी पसंद का ब्राउज़र, जैसे क्रोम।
  • आपकी पसंद का एक IDE या टेक्स्ट एडिटर, जैसे कि डार्ट और फ़्लटर प्लग इन के साथ कॉन्फ़िगर किया गया Android Studio या VS कोड
  • स्पंदन का नवीनतम stable संस्करण (या यदि आप किनारे पर रहने का आनंद लेते हैं तो beta )।
  • आपके Firebase प्रोजेक्ट को बनाने और प्रबंधित करने के लिए एक Google खाता, एक gmail खाते की तरह।
  • firebase कमांड लाइन टूल , आपके जीमेल अकाउंट में लॉग इन है।
  • कोडलैब का नमूना कोड। कोड कैसे प्राप्त करें, इसके लिए अगला चरण देखें।

2. नमूना कोड प्राप्त करें

आइए GitHub से हमारे प्रोजेक्ट के प्रारंभिक संस्करण को डाउनलोड करके शुरू करें।

कमांड लाइन से GitHub रिपॉजिटरी को क्लोन करें:

git clone https://github.com/flutter/codelabs.git flutter-codelabs

वैकल्पिक रूप से, यदि आपके पास GitHub का cli टूल इंस्टॉल है:

gh repo clone flutter/codelabs flutter-codelabs

नमूना कोड को flutter-codelabs निर्देशिका में क्लोन किया जाना चाहिए, जिसमें कोडलैब के संग्रह के लिए कोड होता है। इस कोडलैब का कोड flutter-codelabs/firebase-get-to-know-flutter में है।

flutter-codelabs/firebase-get-to-know-flutter तहत निर्देशिका संरचना स्नैपशॉट की एक श्रृंखला है जहां आपको प्रत्येक नामित चरण के अंत में होना चाहिए। यह चरण 2 है, इसलिए मेल खाने वाली फाइलों का पता लगाना उतना ही आसान है जितना:

cd flutter-codelabs/firebase-get-to-know-flutter/step_02

यदि आप आगे बढ़ना चाहते हैं, या देखें कि एक कदम के बाद कुछ कैसा दिखना चाहिए, तो उस चरण के नाम पर निर्देशिका देखें जिसमें आप रुचि रखते हैं।

स्टार्टर ऐप आयात करें

अपने पसंदीदा IDE में flutter-codelabs/firebase-get-to-know-flutter/step_02 निर्देशिका खोलें या आयात करें। इस निर्देशिका में कोडलैब के लिए शुरुआती कोड है जिसमें अभी तक काम नहीं करने वाला फ़्लटर मीटअप ऐप शामिल है।

काम करने के लिए फाइलों का पता लगाएँ

इस ऐप में कोड कई निर्देशिकाओं में फैला हुआ है। कार्यक्षमता के इस विभाजन को कार्यक्षमता के आधार पर कोड को समूहीकृत करके काम करना आसान बनाने के लिए डिज़ाइन किया गया है।

प्रोजेक्ट में निम्न फ़ाइलों का पता लगाएँ:

  • lib/main.dart : इस फ़ाइल में मुख्य प्रवेश बिंदु और एप्लिकेशन विजेट है।
  • lib/src/widgets.dart : इस फ़ाइल में एप्लिकेशन की स्टाइल को मानकीकृत करने में मदद करने के लिए मुट्ठी भर विजेट हैं। इनका उपयोग स्टार्टर ऐप की स्क्रीन को कंपोज करने के लिए किया जाता है।
  • lib/src/authentication.dart : इस फ़ाइल में फ़ायरबेस ईमेल आधारित प्रमाणीकरण के लिए लॉगिन उपयोगकर्ता अनुभव बनाने के लिए विजेट्स के एक सेट के साथ फ़ायरबेसयूआई ऑथ का आंशिक कार्यान्वयन शामिल है। प्रमाणीकरण प्रवाह के लिए ये विजेट अभी तक स्टार्टर ऐप में उपयोग नहीं किए गए हैं, लेकिन आप इन्हें जल्द ही वायर कर देंगे।

बाकी एप्लिकेशन बनाने के लिए आप आवश्यकतानुसार अतिरिक्त फाइलें जोड़ेंगे।

lib/main.dart फ़ाइल की समीक्षा करना

यह ऐप google_fonts पैकेज का लाभ उठाता है ताकि हम रोबोटो को पूरे ऐप में डिफ़ॉल्ट फॉन्ट बना सकें। प्रेरित पाठक के लिए एक अभ्यास यह है कि आप fonts.google.com को एक्सप्लोर करें और ऐप के विभिन्न हिस्सों में आपके द्वारा खोजे गए फोंट का उपयोग करें।

आप Header , Paragraph और IconAndDetail के रूप में lib/src/widgets.dart से हेल्पर विजेट्स का उपयोग कर रहे हैं। ये विजेट डुप्लीकेट कोड को HomePage में वर्णित पेज लेआउट में अव्यवस्था को कम करते हैं। यह एक सुसंगत रूप और अनुभव को सक्षम करने का अतिरिक्त लाभ है।

यहां बताया गया है कि आपका ऐप Android, iOS, वेब और macOS पर कैसा दिखता है:

ऐप पूर्वावलोकन

3. एक फायरबेस प्रोजेक्ट बनाएं और सेट करें

ईवेंट जानकारी प्रदर्शित करना आपके अतिथियों के लिए बहुत अच्छा है, लेकिन केवल ईवेंट दिखाना किसी के लिए भी बहुत उपयोगी नहीं है. आइए इस ऐप में कुछ गतिशील कार्यक्षमता जोड़ें। इसके लिए आपको Firebase को अपने ऐप से जोड़ना होगा। Firebase के साथ आरंभ करने के लिए, आपको एक Firebase प्रोजेक्ट बनाना और सेट करना होगा।

एक फायरबेस प्रोजेक्ट बनाएं

  1. फायरबेस में साइन इन करें।
  2. Firebase कंसोल में, प्रोजेक्ट जोड़ें (या प्रोजेक्ट बनाएं ) पर क्लिक करें, और अपने Firebase प्रोजेक्ट को Firebase-Flutter-Codelab नाम दें।

4395e4e67c08043a.png

  1. परियोजना निर्माण विकल्पों के माध्यम से क्लिक करें। संकेत मिलने पर Firebase की शर्तें स्वीकार करें. Google Analytics सेट करना छोड़ दें, क्योंकि आप इस ऐप के लिए Analytics का उपयोग नहीं करेंगे।

b7138cde5f2c7b61.png

Firebase प्रोजेक्ट के बारे में और जानने के लिए, Firebase प्रोजेक्ट को समझें देखें.

आप जिस ऐप्लिकेशन का निर्माण कर रहे हैं, वह ऐसे कई Firebase उत्पादों का उपयोग करता है जो वेब ऐप्लिकेशन के लिए उपलब्ध हैं:

  • आपके उपयोगकर्ताओं को आपके ऐप्लिकेशन में साइन इन करने की अनुमति देने के लिए Firebase प्रमाणीकरण .
  • क्लाउड पर संरचित डेटा को सहेजने के लिए क्लाउड फायरस्टोर और डेटा में परिवर्तन होने पर तुरंत सूचना प्राप्त करें।
  • अपने डेटाबेस को सुरक्षित करने के लिए फायरबेस सुरक्षा नियम

इनमें से कुछ उत्पादों को विशेष कॉन्फ़िगरेशन की आवश्यकता होती है या Firebase कंसोल का उपयोग करके सक्षम करने की आवश्यकता होती है।

फायरबेस प्रमाणीकरण के लिए ईमेल साइन-इन सक्षम करें

उपयोगकर्ताओं को वेब ऐप में साइन इन करने की अनुमति देने के लिए, आप इस कोडलैब के लिए ईमेल/पासवर्ड साइन-इन पद्धति का उपयोग करेंगे:

  1. फायरबेस कंसोल में, बाएं पैनल में बिल्ड मेनू का विस्तार करें।
  2. प्रमाणीकरण क्लिक करें, और फिर प्रारंभ करें बटन पर क्लिक करें, फिर साइन-इन विधि टैब पर क्लिक करें (या सीधे साइन-इन विधि टैब पर जाने के लिए यहां क्लिक करें)।
  3. साइन-इन प्रदाताओं की सूची में ईमेल/पासवर्ड पर क्लिक करें, सक्षम करें स्विच को चालू स्थिति पर सेट करें और फिर सहेजें पर क्लिक करें। 58e3e3e23c2f16a4.png

क्लाउड फायरस्टोर सक्षम करें

वेब ऐप चैट संदेशों को सहेजने और नए चैट संदेश प्राप्त करने के लिए क्लाउड फायरस्टोर का उपयोग करता है।

क्लाउड फायरस्टोर सक्षम करें:

  1. फायरबेस कंसोल के बिल्ड सेक्शन में, क्लाउड फायरस्टोर पर क्लिक करें।
  2. डेटाबेस बनाएँ पर क्लिक करें। 99e8429832d23fa3.png
  1. स्टार्ट इन टेस्ट मोड विकल्प चुनें। सुरक्षा नियमों के बारे में अस्वीकरण पढ़ें। परीक्षण मोड सुनिश्चित करता है कि आप विकास के दौरान डेटाबेस को स्वतंत्र रूप से लिख सकते हैं। अगला क्लिक करें। 6be00e26c72ea032.png
  1. अपने डेटाबेस के लिए स्थान का चयन करें (आप केवल डिफ़ॉल्ट का उपयोग कर सकते हैं)। ध्यान दें कि इस स्थान को बाद में बदला नहीं जा सकता। 278656eefcfb0216.png
  2. सक्षम करें क्लिक करें.

4. फायरबेस कॉन्फ़िगरेशन

Flutter के साथ Firebase का उपयोग करने के लिए, आपको FlutterFire लाइब्रेरी का सही ढंग से उपयोग करने के लिए Flutter प्रोजेक्ट को कॉन्फ़िगर करने के लिए एक प्रक्रिया का पालन करने की आवश्यकता है:

  • अपने प्रोजेक्ट में FlutterFire निर्भरता जोड़ें
  • Firebase प्रोजेक्ट पर वांछित प्लेटफ़ॉर्म पंजीकृत करें
  • प्लेटफ़ॉर्म-विशिष्ट कॉन्फ़िगरेशन फ़ाइल डाउनलोड करें, और इसे कोड में जोड़ें।

आपके फ़्लटर ऐप की शीर्ष-स्तरीय निर्देशिका में, उपनिर्देशिकाएँ हैं जिन्हें android , ios , macos और web कहा जाता है। इन निर्देशिकाओं में क्रमशः iOS और Android के लिए प्लेटफ़ॉर्म-विशिष्ट कॉन्फ़िगरेशन फ़ाइलें होती हैं।

निर्भरताओं को कॉन्फ़िगर करें

आपको इस ऐप में उपयोग किए जा रहे दो Firebase उत्पादों के लिए FlutterFire पुस्तकालयों को जोड़ने की आवश्यकता है - Firebase Auth और Cloud Firestore। निर्भरता जोड़ने के लिए निम्नलिखित तीन कमांड चलाएँ।

$ flutter pub add firebase_core

firebase_core सभी Firebase Flutter प्लगइन्स के लिए आवश्यक सामान्य कोड है।

$ flutter pub add firebase_auth

firebase_auth Firebase की प्रमाणीकरण क्षमता के साथ एकीकरण को सक्षम बनाता है।

$ flutter pub add cloud_firestore

cloud_firestore Cloud Firestore डेटा स्टोरेज तक पहुंच को सक्षम बनाता है।

$ flutter pub add provider

firebase_ui_auth पैकेज विशेष रूप से प्रमाणीकरण प्रवाह के साथ डेवलपर वेग बढ़ाने के लिए विजेट और उपयोगिताओं का एक सेट प्रदान करता है।

$ flutter pub add firebase_ui_auth

जब आपने आवश्यक पैकेज जोड़े हैं, तो आपको फायरबेस का उचित उपयोग करने के लिए आईओएस, एंड्रॉइड, मैकओएस और वेब रनर प्रोजेक्ट को भी कॉन्फ़िगर करने की आवश्यकता है। आप provider पैकेज का भी उपयोग कर रहे हैं जो व्यावसायिक तर्क को प्रदर्शन तर्क से अलग करने में सक्षम करेगा।

flutterfire स्थापित करना

FlutterFire CLI अंतर्निहित Firebase CLI पर निर्भर करता है। यदि आपने पहले से ऐसा नहीं किया है, तो सुनिश्चित करें कि आपकी मशीन पर फायरबेस सीएलआई स्थापित है।

इसके बाद, निम्न आदेश चलाकर FlutterFire CLI स्थापित करें:

$ dart pub global activate flutterfire_cli

एक बार स्थापित होने के बाद, flutterfire कमांड विश्व स्तर पर उपलब्ध होगा।

अपने ऐप्स को कॉन्फ़िगर करना

सीएलआई आपके फायरबेस प्रोजेक्ट और चयनित प्रोजेक्ट एप्लिकेशन से जानकारी निकालता है ताकि एक विशिष्ट प्लेटफॉर्म के लिए सभी कॉन्फ़िगरेशन तैयार किए जा सकें।

अपने आवेदन की जड़ में, कॉन्फ़िगर कमांड चलाएँ:

$ flutterfire configure

कॉन्फ़िगरेशन कमांड आपको कई प्रक्रियाओं के माध्यम से मार्गदर्शन करेगा:

  1. एक फायरबेस प्रोजेक्ट का चयन करना (.firebaserc फ़ाइल के आधार पर या फायरबेस कंसोल से)।
  2. संकेत दें कि आप किस प्लेटफ़ॉर्म (जैसे Android, iOS, macOS और वेब) के लिए कॉन्फ़िगरेशन चाहते हैं।
  3. पहचानें कि चुने गए प्लेटफॉर्म के लिए कौन से फायरबेस एप्लिकेशन का कॉन्फ़िगरेशन निकालने के लिए उपयोग किया जाना चाहिए। डिफ़ॉल्ट रूप से, CLI आपके वर्तमान प्रोजेक्ट कॉन्फ़िगरेशन के आधार पर स्वचालित रूप से Firebase ऐप्स से मिलान करने का प्रयास करेगा।
  4. अपने प्रोजेक्ट में एक firebase_options.dart फ़ाइल जनरेट करें।

मैकोज़ कॉन्फ़िगर करें

MacOS पर स्पंदन पूरी तरह से सैंडबॉक्स वाले एप्लिकेशन बनाता है। चूंकि यह एप्लिकेशन फायरबेस सर्वर के साथ संचार करने के लिए नेटवर्क का उपयोग करके एकीकृत हो रहा है, इसलिए आपको अपने एप्लिकेशन को नेटवर्क क्लाइंट विशेषाधिकारों के साथ कॉन्फ़िगर करने की आवश्यकता होगी।

macos/धावक/DebugProfile.entitlements

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
	<key>com.apple.security.cs.allow-jit</key>
	<true/>
	<key>com.apple.security.network.server</key>
	<true/>
  <!-- Add the following two lines -->
	<key>com.apple.security.network.client</key>
	<true/>
</dict>
</plist>

मैकोज़/रनर/रिलीज़.एंटाइटेलमेंट

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.security.app-sandbox</key>
	<true/>
  <!-- Add the following two lines -->
	<key>com.apple.security.network.client</key>
	<true/>
</dict>
</plist>

अधिक विवरण के लिए एंटाइटेलमेंट और ऐप सैंडबॉक्स देखें।

5. उपयोगकर्ता साइन-इन (आरएसवीपी) जोड़ें

अब जब आपने ऐप में फायरबेस जोड़ लिया है, तो आप एक आरएसवीपी बटन सेट कर सकते हैं जो फायरबेस प्रमाणीकरण का उपयोग करने वाले लोगों को पंजीकृत करता है। एंड्रॉइड नेटिव, आईओएस नेटिव और वेब के लिए पूर्व-निर्मित फायरबेसयूआई ऑथ पैकेज हैं, लेकिन स्पंदन के लिए आपको इस क्षमता को बनाने की आवश्यकता होगी।

चरण 2 में आपके द्वारा पुनर्प्राप्त की गई परियोजना में विजेट्स का एक सेट शामिल था जो अधिकांश प्रमाणीकरण प्रवाह के लिए उपयोगकर्ता इंटरफ़ेस को लागू करता है। आप अनुप्रयोग में Firebase प्रमाणीकरण को एकीकृत करने के लिए व्यावसायिक तर्क लागू करेंगे।

प्रदाता के साथ व्यापार तर्क

आप एक केंद्रीकृत एप्लिकेशन स्टेट ऑब्जेक्ट को फ़्लटर विजेट्स के एप्लिकेशन ट्री में उपलब्ध कराने के लिए provider पैकेज का उपयोग करने जा रहे हैं। शुरू करने के लिए, lib/main.dart के शीर्ष पर आयात को संशोधित करें:

lib/main.dart

import 'dart:async';                                     // new
import 'package:firebase_auth/firebase_auth.dart'        // new
    hide EmailAuthProvider, PhoneAuthProvider;           // new
import 'package:firebase_core/firebase_core.dart';       // new
import 'package:firebase_ui_auth/firebase_ui_auth.dart'; // new
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';                 // new

import 'firebase_options.dart';                          // new
import 'src/authentication.dart';                        // new
import 'src/widgets.dart';

import लाइनें फायरबेस कोर और ऑथ का परिचय देती हैं, provider पैकेज में खींचती हैं जिसका उपयोग आप विजेट ट्री के माध्यम से एप्लिकेशन स्टेट ऑब्जेक्ट को उपलब्ध कराने के लिए कर रहे हैं, और इसमें प्रमाणीकरण विजेट शामिल हैं firebase_ui_auth

यह एप्लिकेशन स्टेट ऑब्जेक्ट, ApplicationState , इस चरण के लिए एक मुख्य जिम्मेदारियां है जो कि विजेट ट्री को सचेत करना है कि एक प्रमाणित स्थिति में एक अपडेट था। निम्नलिखित वर्ग को lib/main.dart के अंत में जोड़ें:

lib/main.dart

class ApplicationState extends ChangeNotifier {
  ApplicationState() {
    init();
  }

  bool _loggedIn = false;
  bool get loggedIn => _loggedIn;

  Future<void> init() async {
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform);

    FirebaseUIAuth.configureProviders([
      EmailAuthProvider(),
    ]);

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loggedIn = true;
      } else {
        _loggedIn = false;
      }
      notifyListeners();
    });
  }
}

हम यहां एक प्रदाता का उपयोग ऐप से संवाद करने के लिए कर रहे हैं कि उपयोगकर्ता की लॉगिन स्थिति की स्थिति, और कुछ नहीं। किसी उपयोगकर्ता को लॉगिन करने के लिए, हम firebase_ui_auth द्वारा प्रदान किए गए UI का उपयोग करने जा रहे हैं जो आपके एप्लिकेशन के लिए लॉगिन स्क्रीन को त्वरित रूप से बूटस्ट्रैप करने का एक शानदार तरीका है।

प्रमाणीकरण प्रवाह को एकीकृत करना

अब जब आपके पास एप्लिकेशन स्थिति की शुरुआत है, तो एप्लिकेशन स्थिति को ऐप इनिशियलाइज़ेशन में वायर करने और प्रमाणीकरण प्रवाह को HomePage में जोड़ने का समय आ गया है। provider पैकेज के माध्यम से एप्लिकेशन स्थिति को एकीकृत करने के लिए मुख्य प्रवेश बिंदु को अपडेट करें:

lib/main.dart

void main() {
  // Modify from here
  WidgetsFlutterBinding.ensureInitialized();

  runApp(ChangeNotifierProvider(
    create: (context) => ApplicationState(),
    builder: ((context, child) => const App()),
  ));
  // to here.
}

main फ़ंक्शन में संशोधन प्रदाता पैकेज को ChangeNotifierProvider विजेट का उपयोग करके एप्लिकेशन स्थिति ऑब्जेक्ट को तुरंत चालू करने के लिए जिम्मेदार बनाता है। आप इस विशिष्ट प्रदाता वर्ग का उपयोग कर रहे हैं क्योंकि एप्लिकेशन स्थिति ऑब्जेक्ट ChangeNotifier का विस्तार करता है और यह provider पैकेज को यह जानने में सक्षम बनाता है कि आश्रित विजेट को कब फिर से प्रदर्शित करना है।

चूंकि हम Flutter के लिए FirebaseUI का उपयोग कर रहे हैं, इसलिए हम FirebaseUI द्वारा हमारे लिए प्रदान की जाने वाली विभिन्न स्क्रीन पर नेविगेट करने के लिए अपने ऐप को अपडेट करने जा रहे हैं। ऐसा करने के लिए हम एक initialRoute प्रॉपर्टी जोड़ते हैं और अपनी पसंदीदा स्क्रीन जोड़ते हैं जिसे हम routes प्रॉपर्टी के तहत रूट कर सकते हैं। परिवर्तन इस तरह दिखना चाहिए:

lib/main.dart

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      //Start adding here
      initialRoute: '/home',
      routes: {
        '/home': (context) {
          return const HomePage();
        },
        '/sign-in': ((context) {
          return SignInScreen(
            actions: [
              ForgotPasswordAction(((context, email) {
                Navigator.of(context)
                    .pushNamed('/forgot-password', arguments: {'email': email});
              })),
              AuthStateChangeAction(((context, state) {
                if (state is SignedIn || state is UserCreated) {
                  var user = (state is SignedIn)
                      ? state.user
                      : (state as UserCreated).credential.user;
                  if (user == null) {
                    return;
                  }
                  if (state is UserCreated) {
                    user.updateDisplayName(user.email!.split('@')[0]);
                  }
                  if (!user.emailVerified) {
                    user.sendEmailVerification();
                    const snackBar = SnackBar(
                        content: Text(
                            'Please check your email to verify your email address'));
                    ScaffoldMessenger.of(context).showSnackBar(snackBar);
                  }
                  Navigator.of(context).pushReplacementNamed('/home');
                }
              })),
            ],
          );
        }),
        '/forgot-password': ((context) {
          final arguments = ModalRoute.of(context)?.settings.arguments
              as Map<String, dynamic>?;

          return ForgotPasswordScreen(
            email: arguments?['email'] as String,
            headerMaxExtent: 200,
          );
        }),
        '/profile': ((context) {
          return ProfileScreen(
            providers: [],
            actions: [
              SignedOutAction(
                ((context) {
                  Navigator.of(context).pushReplacementNamed('/home');
                }),
              ),
            ],
          );
        })
      },
      // end adding here
      title: 'Firebase Meetup',
      theme: ThemeData(
        buttonTheme: Theme.of(context).buttonTheme.copyWith(
              highlightColor: Colors.deepPurple,
            ),
        primarySwatch: Colors.deepPurple,
        textTheme: GoogleFonts.robotoTextTheme(
          Theme.of(context).textTheme,
        ),
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
    );
  }
}

प्रमाणीकरण प्रवाह की नई स्थिति के आधार पर प्रत्येक स्क्रीन में एक अलग प्रकार की क्रिया जुड़ी होती है। प्रमाणीकरण में अधिकांश राज्य परिवर्तनों के बाद, हम पसंदीदा स्क्रीन पर वापस जाने में सक्षम होते हैं, चाहे वह होम स्क्रीन हो या प्रोफ़ाइल जैसी कोई भिन्न स्क्रीन। अंत में, HomePage की बिल्ड विधि को अपडेट करके एप्लिकेशन स्थिति को AuthFunc के साथ एकीकृत करें:

lib/main.dart

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

  @override
  Widget build(BuildContext context) {
    return Consumer<ApplicationState>(
        builder: (context, appState, child) => Scaffold(
              appBar: AppBar(
                title: const Text('Firebase Meetup'),
              ),
              body: ListView(
                children: <Widget>[
                  Image.asset('assets/codelab.png'),
                  const SizedBox(height: 8),
                  const IconAndDetail(Icons.calendar_today, 'October 30'),
                  const IconAndDetail(Icons.location_city, 'San Francisco'),
                  // Add from here
                  Consumer<ApplicationState>(
                    builder: (context, appState, _) => AuthFunc(
                        loggedIn: appState.loggedIn,
                        signOut: () {
                          FirebaseAuth.instance.signOut();
                        }),
                  ),
                  // to here
                  const Divider(
                    height: 8,
                    thickness: 1,
                    indent: 8,
                    endIndent: 8,
                    color: Colors.grey,
                  ),
                  const Header("What we'll be doing"),
                  const Paragraph(
                    'Join us for a day full of Firebase Workshops and Pizza!',
                  ),
                ],
              ),
            ));
  }
}

आप AuthFunc विजेट को इंस्टेंट करते हैं, और इसे Consumer विजेट में लपेटते हैं। उपभोक्ता विजेट सामान्य तरीका है कि provider पैकेज का उपयोग पेड़ के हिस्से के पुनर्निर्माण के लिए किया जा सकता है जब एप्लिकेशन स्थिति बदलती है। AuthFunc विजेट पूरक विजेट है जिसका अब आप परीक्षण करेंगे।

प्रमाणीकरण प्रवाह का परीक्षण

cdf2d25e436bd48d.png

यहां प्रमाणीकरण प्रवाह की शुरुआत है, जहां उपयोगकर्ता SignInScreen आरंभ करने के लिए आरएसवीपी बटन पर टैप कर सकता है।

2a2cd6d69d172369.png

ईमेल दर्ज करने पर, सिस्टम पुष्टि करता है कि क्या उपयोगकर्ता पहले से पंजीकृत है, उस स्थिति में उपयोगकर्ता को पासवर्ड के लिए संकेत दिया जाता है, वैकल्पिक रूप से यदि उपयोगकर्ता पंजीकृत नहीं है, तो वे पंजीकरण फॉर्म के माध्यम से जाते हैं।

e5e65065dba36b54.png

त्रुटि प्रबंधन प्रवाह की जांच करने के लिए एक छोटा पासवर्ड (छह वर्णों से कम) दर्ज करने का प्रयास करना सुनिश्चित करें। यदि उपयोगकर्ता पंजीकृत है, तो वे इसके बजाय पासवर्ड देखेंगे।

इस पृष्ठ पर त्रुटि प्रबंधन की जांच करने के लिए गलत पासवर्ड दर्ज करना सुनिश्चित करें। अंत में, एक बार जब उपयोगकर्ता लॉग इन हो जाता है, तो आप लॉग इन अनुभव देखेंगे जो उपयोगकर्ता को फिर से लॉग आउट करने की क्षमता प्रदान करता है।

4ed811a25b0cf816.png

और इसके साथ ही, आपने प्रमाणीकरण प्रवाह लागू कर दिया है। बधाई!

6. क्लाउड फायरस्टोर को संदेश लिखें

यह जानकर कि उपयोगकर्ता आ रहे हैं, बहुत अच्छा है, लेकिन आइए मेहमानों को ऐप में कुछ और करने दें। क्या होगा यदि वे एक अतिथि पुस्तिका में संदेश छोड़ सकते हैं? वे साझा कर सकते हैं कि वे आने के लिए उत्साहित क्यों हैं या वे किससे मिलने की उम्मीद करते हैं।

उन चैट संदेशों को संग्रहीत करने के लिए जो उपयोगकर्ता ऐप में लिखते हैं, आप क्लाउड फायरस्टोर का उपयोग करेंगे।

डेटा मॉडल

Cloud Firestore एक NoSQL डेटाबेस है, और डेटाबेस में संग्रहीत डेटा को संग्रह, दस्तावेज़, फ़ील्ड और उप-संग्रह में विभाजित किया जाता है। आप चैट के प्रत्येक संदेश को guestbook नामक एक शीर्ष-स्तरीय संग्रह में एक दस्तावेज़ के रूप में संग्रहीत करेंगे।

7c20dc8424bb1d84.png

फायरस्टोर में संदेश जोड़ें

इस खंड में, आप डेटाबेस में नए संदेश लिखने के लिए उपयोगकर्ताओं के लिए कार्यक्षमता जोड़ेंगे। सबसे पहले, आप UI तत्व (फ़ॉर्म फ़ील्ड और भेजें बटन) जोड़ते हैं, और फिर आप उस कोड को जोड़ते हैं जो इन तत्वों को डेटाबेस से जोड़ता है।

सबसे पहले, cloud_firestore पैकेज और dart dart:async के लिए आयात जोड़ें।

lib/main.dart

import 'dart:async';                                    // new

import 'package:cloud_firestore/cloud_firestore.dart';  // new
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';

import 'firebase_options.dart';
import 'src/authentication.dart';
import 'src/widgets.dart';

एक संदेश फ़ील्ड और एक भेजें बटन के UI तत्वों के निर्माण के लिए, lib/main.dart के नीचे एक नया स्टेटफुल विजेट GuestBook जोड़ें।

lib/main.dart

class GuestBook extends StatefulWidget {
  const GuestBook({required this.addMessage, super.key});
  final FutureOr<void> Function(String message) addMessage;

  @override
  State<GuestBook> createState() => _GuestBookState();
}

class _GuestBookState extends State<GuestBook> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_GuestBookState');
  final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Form(
        key: _formKey,
        child: Row(
          children: [
            Expanded(
              child: TextFormField(
                controller: _controller,
                decoration: const InputDecoration(
                  hintText: 'Leave a message',
                ),
                validator: (value) {
                  if (value == null || value.isEmpty) {
                    return 'Enter your message to continue';
                  }
                  return null;
                },
              ),
            ),
            const SizedBox(width: 8),
            StyledButton(
              onPressed: () async {
                if (_formKey.currentState!.validate()) {
                  await widget.addMessage(_controller.text);
                  _controller.clear();
                }
              },
              child: Row(
                children: const [
                  Icon(Icons.send),
                  SizedBox(width: 4),
                  Text('SEND'),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

यहां रुचि के कुछ बिंदु हैं। सबसे पहले, आप एक फॉर्म को तत्काल कर रहे हैं ताकि आप संदेश को सत्यापित कर सकें कि वास्तव में कुछ सामग्री है, और यदि कोई नहीं है तो उपयोगकर्ता को एक त्रुटि संदेश दिखाएं। किसी प्रपत्र को सत्यापित करने के तरीके में प्रपत्र के पीछे प्रपत्र स्थिति तक पहुँच शामिल है, और इसके लिए आप GlobalKey का उपयोग करते हैं। कुंजियों के बारे में अधिक जानकारी के लिए, और उनका उपयोग कैसे करें, कृपया फ़्लटर विजेट्स 101 एपिसोड "कब टू यूज़ कीज़" देखें

यह भी ध्यान दें कि जिस तरह से विजेट रखे गए हैं, आपके पास एक Row है, जिसमें TextFormField और StyledButton है, जिसमें स्वयं Row है। यह भी ध्यान दें कि TextFormField एक Expanded विजेट में लिपटा हुआ है, यह TextFormField को पंक्ति में कोई अतिरिक्त स्थान लेने के लिए मजबूर करता है। यह समझने के लिए कि इसकी आवश्यकता क्यों है, कृपया बाधाओं को समझना पढ़ें।

अब जब आपके पास एक विजेट है जो उपयोगकर्ता को अतिथि पुस्तक में जोड़ने के लिए कुछ पाठ दर्ज करने में सक्षम बनाता है, तो आपको इसे स्क्रीन पर लाने की आवश्यकता है। ऐसा करने के लिए, ListView के बच्चों के नीचे निम्नलिखित दो पंक्तियों को जोड़ने के लिए HomePage के मुख्य भाग को संपादित करें:

const Header("What we'll be doing"),
const Paragraph(
  'Join us for a day full of Firebase Workshops and Pizza!',
),
// Add the following two lines.
const Header('Discussion'),
GuestBook(addMessage: (message) => print(message)),

हालांकि यह विजेट प्रदर्शित करने के लिए पर्याप्त है, लेकिन यह कुछ भी उपयोगी करने के लिए पर्याप्त नहीं है। आप इसे कार्यशील बनाने के लिए शीघ्र ही इस कोड को अपडेट करेंगे।

ऐप पूर्वावलोकन

भेजें बटन पर क्लिक करने वाला उपयोगकर्ता नीचे दिए गए कोड स्निपेट को ट्रिगर करेगा। यह डेटाबेस के guestbook संग्रह में संदेश इनपुट फ़ील्ड की सामग्री जोड़ता है। विशेष रूप से, addMessageToGuestBook विधि संदेश सामग्री को एक नए दस्तावेज़ में (स्वचालित रूप से जेनरेट की गई आईडी के साथ) guestbook संग्रह में जोड़ती है।

ध्यान दें कि FirebaseAuth.instance.currentUser.uid ऑटो-जेनरेटेड यूनिक आईडी का एक संदर्भ है जो फायरबेस प्रमाणीकरण सभी लॉग-इन उपयोगकर्ताओं के लिए देता है।

lib/main.dart फ़ाइल में एक और बदलाव करें। addMessageToGuestBook विधि जोड़ें। आप अगले चरण में यूजर इंटरफेस और इस क्षमता को एक साथ तार देंगे।

lib/main.dart

class ApplicationState extends ChangeNotifier {

  // Current content of ApplicationState elided ...

  // Add from here
  Future<DocumentReference> addMessageToGuestBook(String message) {
    if (!_loggedIn) {
      throw Exception('Must be logged in');
    }

    return FirebaseFirestore.instance
        .collection('guestbook')
        .add(<String, dynamic>{
      'text': message,
      'timestamp': DateTime.now().millisecondsSinceEpoch,
      'name': FirebaseAuth.instance.currentUser!.displayName,
      'userId': FirebaseAuth.instance.currentUser!.uid,
    });
  }
  // To here
}

डेटाबेस में UI को तार-तार करना

आपके पास एक UI है जहां उपयोगकर्ता उस पाठ को दर्ज कर सकता है जिसे वे अतिथि पुस्तक में जोड़ना चाहते हैं, और आपके पास क्लाउड फायरस्टोर में प्रविष्टि जोड़ने के लिए कोड है। अब आपको बस इतना करना है कि दोनों को एक साथ तार दें। lib/main.dart में HomePage विजेट में निम्नलिखित परिवर्तन करें।

lib/main.dart

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Firebase Meetup'),
      ),
      body: ListView(
        children: <Widget>[
          Image.asset('assets/codelab.png'),
          const SizedBox(height: 8),
          const IconAndDetail(Icons.calendar_today, 'October 30'),
          const IconAndDetail(Icons.location_city, 'San Francisco'),
          Consumer<ApplicationState>(
            builder: (context, appState, _) => AuthFunc(
                loggedIn: appState.loggedIn,
                signOut: () {
                  FirebaseAuth.instance.signOut();
                }),
          ),
          const Divider(
            height: 8,
            thickness: 1,
            indent: 8,
            endIndent: 8,
            color: Colors.grey,
          ),
          const Header("What we'll be doing"),
          const Paragraph(
            'Join us for a day full of Firebase Workshops and Pizza!',
          ),
          // Modify from here
          Consumer<ApplicationState>(
            builder: (context, appState, _) => Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                if (appState.loggedIn) ...[
                  const Header('Discussion'),
                  GuestBook(
                    addMessage: (message) =>
                        appState.addMessageToGuestBook(message),
                  ),
                ],
              ],
            ),
          ),
          // To here.
        ],
      ),
    );
  }
}

आपने इस चरण की शुरुआत में वापस जोड़ी गई दो पंक्तियों को पूर्ण कार्यान्वयन के साथ बदल दिया है। आप फिर से Consumer<ApplicationState> का उपयोग कर रहे हैं ताकि आपके द्वारा प्रस्तुत किए जा रहे पेड़ के हिस्से के लिए एप्लिकेशन स्थिति उपलब्ध हो सके। यह आपको UI में संदेश दर्ज करने वाले किसी व्यक्ति पर प्रतिक्रिया करने और डेटाबेस में प्रकाशित करने में सक्षम बनाता है। अगले भाग में आप परीक्षण करेंगे कि क्या जोड़े गए संदेश डेटाबेस में प्रकाशित हुए हैं।

संदेश भेजने का परीक्षण करें

  1. सुनिश्चित करें कि आपने ऐप में साइन इन किया है।
  2. एक संदेश दर्ज करें जैसे "अरे वहाँ!", और फिर भेजें क्लिक करें।

यह क्रिया आपके क्लाउड फायरस्टोर डेटाबेस को संदेश लिखती है। हालाँकि, आपको अभी तक अपने वास्तविक फ़्लटर ऐप में संदेश दिखाई नहीं देगा क्योंकि आपको अभी भी डेटा पुनर्प्राप्त करने को लागू करने की आवश्यकता है। आप इसे अगले चरण में करेंगे।

लेकिन आप नए जोड़े गए संदेश को फायरबेस कंसोल में देख सकते हैं।

फायरबेस कंसोल में, डेटाबेस डैशबोर्ड में, आपको अपने नए जोड़े गए संदेश के साथ guestbook संग्रह देखना चाहिए। यदि आप संदेश भेजते रहते हैं, तो आपके गेस्टबुक संग्रह में कई दस्तावेज़ होंगे, जैसे:

फायरबेस कंसोल

713870af0b3b63c.png

7. संदेश पढ़ें

यह अच्छा है कि मेहमान डेटाबेस में संदेश लिख सकते हैं, लेकिन वे उन्हें अभी तक ऐप में नहीं देख सकते हैं। चलो इसे ठीक करते हैं!

संदेशों को सिंक्रनाइज़ करें

संदेशों को प्रदर्शित करने के लिए, आपको श्रोताओं को जोड़ना होगा जो डेटा बदलने पर ट्रिगर करते हैं और फिर एक UI तत्व बनाते हैं जो नए संदेश दिखाता है। आप एप्लिकेशन स्थिति में कोड जोड़ेंगे जो ऐप से नए जोड़े गए संदेशों को सुनता है।

GuestBook विजेट के ठीक ऊपर निम्न मान वर्ग। यह वर्ग आपके द्वारा क्लाउड फायरस्टोर में संग्रहीत किए जा रहे डेटा के संरचित दृश्य को उजागर करता है।

lib/main.dart

class GuestBookMessage {
  GuestBookMessage({required this.name, required this.message});
  final String name;
  final String message;
}

ApplicationState के अनुभाग में जहां आप राज्य और गेटर्स को परिभाषित करते हैं, निम्नलिखित नई लाइनें जोड़ें:

lib/main.dart

  bool _loggedIn = false;
  bool get loggedIn => _loggedIn;

  // Add from here
  StreamSubscription<QuerySnapshot>? _guestBookSubscription;
  List<GuestBookMessage> _guestBookMessages = [];
  List<GuestBookMessage> get guestBookMessages => _guestBookMessages;
  // to here.

और अंत में, ApplicationState के इनिशियलाइज़ेशन सेक्शन में, उपयोगकर्ता द्वारा लॉग इन करने पर दस्तावेज़ संग्रह पर एक क्वेरी की सदस्यता के लिए निम्नलिखित जोड़ें और लॉग आउट होने पर सदस्यता समाप्त करें।

lib/main.dart

  Future<void> init() async {
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform);

    FirebaseUIAuth.configureProviders([
      EmailAuthProvider(),
    ]);
    
    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loggedIn = true;
        _guestBookSubscription = FirebaseFirestore.instance
            .collection('guestbook')
            .orderBy('timestamp', descending: true)
            .snapshots()
            .listen((snapshot) {
          _guestBookMessages = [];
          for (final document in snapshot.docs) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'] as String,
                message: document.data()['text'] as String,
              ),
            );
          }
          notifyListeners();
        });
      } else {
        _loggedIn = false;
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
      }
      notifyListeners();
    });
  }

यह खंड महत्वपूर्ण है, क्योंकि यहां आप guestbook संग्रह पर एक क्वेरी बनाते हैं, और इस संग्रह की सदस्यता लेने और सदस्यता समाप्त करने को संभालते हैं। आप स्ट्रीम को सुनते हैं, जहां आप guestbook संग्रह में संदेशों के स्थानीय कैश का पुनर्निर्माण करते हैं, और इस सदस्यता का संदर्भ भी संग्रहीत करते हैं ताकि आप बाद में इसकी सदस्यता समाप्त कर सकें। यहां बहुत कुछ चल रहा है, और डिबगर में कुछ समय बिताने के लायक है कि एक स्पष्ट मानसिक मॉडल प्राप्त करने के लिए क्या होता है।

अधिक जानकारी के लिए, क्लाउड फायरस्टोर दस्तावेज़ीकरण देखें।

GuestBook विजेट में आपको इस बदलती स्थिति को यूजर इंटरफेस से जोड़ने की जरूरत है। आप इसके कॉन्फ़िगरेशन के हिस्से के रूप में संदेशों की सूची जोड़कर विजेट को संशोधित करते हैं।

lib/main.dart

class GuestBook extends StatefulWidget {
  // Modify the following line
  const GuestBook({super.key, required this.addMessage, required this.messages,});
  final FutureOr<void> Function(String message) addMessage;
  final List<GuestBookMessage> messages; // new

  @override
  _GuestBookState createState() => _GuestBookState();
}

इसके बाद, हम इस नए कॉन्फ़िगरेशन को _GuestBookState में निम्नानुसार build विधि को संशोधित करके उजागर करते हैं।

lib/main.dart

class _GuestBookState extends State<GuestBook> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_GuestBookState');
  final _controller = TextEditingController();

  @override
  // Modify from here
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // to here.
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Form(
            key: _formKey,
            child: Row(
              children: [
                Expanded(
                  child: TextFormField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      hintText: 'Leave a message',
                    ),
                    validator: (value) {
                      if (value == null || value.isEmpty) {
                        return 'Enter your message to continue';
                      }
                      return null;
                    },
                  ),
                ),
                const SizedBox(width: 8),
                StyledButton(
                  onPressed: () async {
                    if (_formKey.currentState!.validate()) {
                      await widget.addMessage(_controller.text);
                      _controller.clear();
                    }
                  },
                  child: Row(
                    children: const [
                      Icon(Icons.send),
                      SizedBox(width: 4),
                      Text('SEND'),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
        // Modify from here
        const SizedBox(height: 8),
        for (var message in widget.messages)
          Paragraph('${message.name}: ${message.message}'),
        const SizedBox(height: 8),
      ],
      // to here.
    );
  }
}

आप बिल्ड विधि की पिछली सामग्री को Column विजेट के साथ लपेटते हैं, और फिर Column के बच्चों की पूंछ पर आप संदेशों की सूची में प्रत्येक संदेश के लिए एक नया Paragraph उत्पन्न करने के लिए एक संग्रह जोड़ते हैं।

अंत में, अब आपको नए messages पैरामीटर के साथ GuestBook को सही ढंग से बनाने के लिए HomePage के मुख्य भाग को अपडेट करने की आवश्यकता है।

lib/main.dart

Consumer<ApplicationState>(
  builder: (context, appState, _) => Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      if (appState.loginState == ApplicationLoginState.loggedIn) ...[
        const Header('Discussion'),
        GuestBook(
          addMessage: (message) =>
              appState.addMessageToGuestBook(message),
          messages: appState.guestBookMessages, // new
        ),
      ],
    ],
  ),
),

संदेशों को सिंक्रनाइज़ करने का परीक्षण करें

क्लाउड फायरस्टोर स्वचालित रूप से और तुरंत डेटाबेस की सदस्यता लेने वाले ग्राहकों के साथ डेटा को सिंक्रनाइज़ करता है।

  1. आपके द्वारा डेटाबेस में पहले बनाए गए संदेशों को ऐप में प्रदर्शित किया जाना चाहिए। नए संदेश लिखने के लिए स्वतंत्र महसूस करें; उन्हें तत्काल प्रकट होना चाहिए।
  2. यदि आप अपने कार्यक्षेत्र को कई विंडो या टैब में खोलते हैं, तो संदेश वास्तविक समय में सभी टैब में समन्वयित होंगे।
  3. (वैकल्पिक) आप Firebase कंसोल के डेटाबेस अनुभाग में सीधे नए संदेशों को मैन्युअल रूप से हटाने, संशोधित करने या जोड़ने का प्रयास कर सकते हैं; UI में कोई भी परिवर्तन दिखाई देना चाहिए।

बधाई हो! आप अपने ऐप में क्लाउड फायरस्टोर दस्तावेज़ पढ़ रहे हैं!

ऐप पी समीक्षा

8. बुनियादी सुरक्षा नियम स्थापित करें

आपने शुरू में परीक्षण मोड का उपयोग करने के लिए क्लाउड फायरस्टोर की स्थापना की, जिसका अर्थ है कि आपका डेटाबेस पढ़ने और लिखने के लिए खुला है। हालाँकि, आपको केवल विकास के प्रारंभिक चरणों के दौरान ही परीक्षण मोड का उपयोग करना चाहिए। सर्वोत्तम अभ्यास के रूप में, आपको अपना ऐप विकसित करते समय अपने डेटाबेस के लिए सुरक्षा नियम स्थापित करने चाहिए। सुरक्षा आपके ऐप की संरचना और व्यवहार का अभिन्न अंग होनी चाहिए।

सुरक्षा नियम आपको अपने डेटाबेस में दस्तावेज़ों और संग्रहों तक पहुँच को नियंत्रित करने की अनुमति देते हैं। लचीला नियम सिंटैक्स आपको ऐसे नियम बनाने की अनुमति देता है जो किसी विशिष्ट दस्तावेज़ पर संचालन के लिए पूरे डेटाबेस में सभी लिखने से मेल खाते हैं।

आप Firebase कंसोल में Cloud Firestore के लिए सुरक्षा नियम लिख सकते हैं:

  1. फायरबेस कंसोल के डेवलप सेक्शन में, डेटाबेस पर क्लिक करें, और फिर नियम टैब चुनें (या सीधे नियम टैब पर जाने के लिए यहां क्लिक करें )।
  2. नियमों के सार्वजनिक होने के बारे में चेतावनी के साथ आपको निम्नलिखित डिफ़ॉल्ट सुरक्षा नियम देखना चाहिए।

7767a2d2e64e7275.png

संग्रह की पहचान करें

सबसे पहले, उन संग्रहों की पहचान करें जिन पर ऐप डेटा लिखता है।

match /databases/{database}/documents , उस संग्रह की पहचान करें जिसे आप सुरक्षित करना चाहते हैं:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
     // You'll add rules here in the next step.
  }
}

सुरक्षा नियम जोड़ें

चूंकि आपने प्रत्येक गेस्टबुक दस्तावेज़ में प्रमाणीकरण UID को एक फ़ील्ड के रूप में उपयोग किया है, आप प्रमाणीकरण UID प्राप्त कर सकते हैं और सत्यापित कर सकते हैं कि दस्तावेज़ को लिखने का प्रयास करने वाले किसी भी व्यक्ति के पास मिलान करने वाला प्रमाणीकरण UID है।

नीचे दिखाए अनुसार अपने नियम सेट में पढ़ने और लिखने के नियम जोड़ें:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow write:
        if request.auth.uid == request.resource.data.userId;
    }
  }
}

अब, अतिथिपुस्तिका के लिए, केवल साइन-इन उपयोगकर्ता ही संदेश पढ़ सकते हैं (कोई भी संदेश!), लेकिन केवल संदेश का लेखक ही संदेश को संपादित कर सकता है।

सत्यापन नियम जोड़ें

यह सुनिश्चित करने के लिए डेटा सत्यापन जोड़ें कि दस्तावेज़ में सभी अपेक्षित फ़ील्ड मौजूद हैं:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /guestbook/{entry} {
      allow read: if request.auth.uid != null;
      allow write:
      if request.auth.uid == request.resource.data.userId
          && "name" in request.resource.data
          && "text" in request.resource.data
          && "timestamp" in request.resource.data;
    }
  }
}

9. बोनस चरण: आपने जो सीखा है उसका अभ्यास करें

एक सहभागी की प्रतिसाद स्थिति रिकॉर्ड करें

अभी, आपका ऐप लोगों को केवल तभी चैट करना शुरू करने देता है, जब वे ईवेंट में रुचि रखते हैं। साथ ही, किसी के आने के बारे में आप केवल तभी जान सकते हैं जब वे उसे चैट में पोस्ट करते हैं। आइए संगठित हों और लोगों को बताएं कि कितने लोग आ रहे हैं।

आप एप्लिकेशन स्थिति में कुछ नई क्षमताएं जोड़ने जा रहे हैं। पहला यह है कि लॉग इन उपयोगकर्ता को नामांकित करने की क्षमता है कि वे भाग ले रहे हैं या नहीं। दूसरी क्षमता एक काउंटर है कि वास्तव में कितने लोग भाग ले रहे हैं।

lib/main.dart में, UI कोड को इस स्थिति के साथ इंटरैक्ट करने में सक्षम करने के लिए एक्सेसर्स सेक्शन में निम्नलिखित जोड़ें:

lib/main.dart

int _attendees = 0;
int get attendees => _attendees;

Attending _attending = Attending.unknown;
StreamSubscription<DocumentSnapshot>? _attendingSubscription;
Attending get attending => _attending;
set attending(Attending attending) {
  final userDoc = FirebaseFirestore.instance
      .collection('attendees')
      .doc(FirebaseAuth.instance.currentUser!.uid);
  if (attending == Attending.yes) {
    userDoc.set(<String, dynamic>{'attending': true});
  } else {
    userDoc.set(<String, dynamic>{'attending': false});
  }
}

ApplicationState की init विधि को इस प्रकार अपडेट करें:

lib/main.dart

  Future<void> init() async {
    await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform);

    FirebaseUIAuth.configureProviders([
      EmailAuthProvider(),
    ]);

    // Add from here
    FirebaseFirestore.instance
        .collection('attendees')
        .where('attending', isEqualTo: true)
        .snapshots()
        .listen((snapshot) {
      _attendees = snapshot.docs.length;
      notifyListeners();
    });
    // To here

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loginState = ApplicationLoginState.loggedIn;
        _guestBookSubscription = FirebaseFirestore.instance
            .collection('guestbook')
            .orderBy('timestamp', descending: true)
            .snapshots()
            .listen((snapshot) {
          _guestBookMessages = [];
          for (final document in snapshot.docs) {
            _guestBookMessages.add(
              GuestBookMessage(
                name: document.data()['name'] as String,
                message: document.data()['text'] as String,
              ),
            );
          }
          notifyListeners();
        });
        // Add from here
        _attendingSubscription = FirebaseFirestore.instance
            .collection('attendees')
            .doc(user.uid)
            .snapshots()
            .listen((snapshot) {
          if (snapshot.data() != null) {
            if (snapshot.data()!['attending'] as bool) {
              _attending = Attending.yes;
            } else {
              _attending = Attending.no;
            }
          } else {
            _attending = Attending.unknown;
          }
          notifyListeners();
        });
        // to here
      } else {
        _loginState = ApplicationLoginState.loggedOut;
        _guestBookMessages = [];
        _guestBookSubscription?.cancel();
        _attendingSubscription?.cancel(); // new
      }
      notifyListeners();
    });
  }

उपरोक्त उपस्थित लोगों की संख्या का पता लगाने के लिए एक हमेशा सब्सक्राइब की गई क्वेरी जोड़ता है, और एक दूसरी क्वेरी जो केवल तब सक्रिय होती है जब उपयोगकर्ता यह पता लगाने के लिए लॉग इन होता है कि उपयोगकर्ता भाग ले रहा है या नहीं। अगला, GuestBookMessage घोषणा के बाद निम्नलिखित गणना जोड़ें:

lib/main.dart

enum Attending { yes, no, unknown }

अब आप एक नए विजेट को परिभाषित करने जा रहे हैं जो पुराने के रेडियो बटन की तरह काम करता है। यह एक अनिश्चित स्थिति में शुरू होता है, न तो हां और न ही चयनित के साथ, लेकिन एक बार जब उपयोगकर्ता यह चुन लेता है कि वे भाग ले रहे हैं या नहीं, तो आप उस विकल्प को एक भरे हुए बटन के साथ हाइलाइट करते हैं, और दूसरा विकल्प एक फ्लैट रेंडरिंग के साथ घटता है।

lib/main.dart

class YesNoSelection extends StatelessWidget {
  const YesNoSelection(
      {super.key, required this.state, required this.onSelection});
  final Attending state;
  final void Function(Attending selection) onSelection;

  @override
  Widget build(BuildContext context) {
    switch (state) {
      case Attending.yes:
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              ElevatedButton(
                style: ElevatedButton.styleFrom(elevation: 0),
                onPressed: () => onSelection(Attending.yes),
                child: const Text('YES'),
              ),
              const SizedBox(width: 8),
              TextButton(
                onPressed: () => onSelection(Attending.no),
                child: const Text('NO'),
              ),
            ],
          ),
        );
      case Attending.no:
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              TextButton(
                onPressed: () => onSelection(Attending.yes),
                child: const Text('YES'),
              ),
              const SizedBox(width: 8),
              ElevatedButton(
                style: ElevatedButton.styleFrom(elevation: 0),
                onPressed: () => onSelection(Attending.no),
                child: const Text('NO'),
              ),
            ],
          ),
        );
      default:
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            children: [
              StyledButton(
                onPressed: () => onSelection(Attending.yes),
                child: const Text('YES'),
              ),
              const SizedBox(width: 8),
              StyledButton(
                onPressed: () => onSelection(Attending.no),
                child: const Text('NO'),
              ),
            ],
          ),
        );
    }
  }
}

इसके बाद, आपको YesNoSelection का लाभ उठाने के लिए HomePage की बिल्ड विधि को अपडेट करने की आवश्यकता है, जिससे लॉग इन उपयोगकर्ता को नामांकित करने में सक्षम बनाता है यदि वे भाग ले रहे हैं। आप इस घटना के लिए उपस्थित लोगों की संख्या भी प्रदर्शित करेंगे।

lib/main.dart

Consumer<ApplicationState>(
  builder: (context, appState, _) => Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // Add from here
      if (appState.attendees >= 2)
        Paragraph('${appState.attendees} people going')
      else if (appState.attendees == 1)
        const Paragraph('1 person going')
      else
        const Paragraph('No one going'),
      // To here.
      if (appState.loggedIn) ...[
        // Add from here
        YesNoSelection(
          state: appState.attending,
          onSelection: (attending) => appState.attending = attending,
        ),
        // To here.
        const Header('Discussion'),
        GuestBook(
          addMessage: (message) =>
              appState.addMessageToGuestBook(message),
          messages: appState.guestBookMessages,
        ),
      ],
    ],
  ),
),

नियम जोड़ें

चूंकि आपके पास पहले से ही कुछ नियम स्थापित हैं, आप बटनों के साथ जो नया डेटा जोड़ रहे हैं, उसे अस्वीकार कर दिया जाएगा। attendees के संग्रह में जोड़ने की अनुमति देने के लिए आपको नियमों को अपडेट करना होगा।

attendees के संग्रह के लिए, चूंकि आपने दस्तावेज़ के नाम के रूप में प्रमाणीकरण UID का उपयोग किया है, आप इसे पकड़ सकते हैं और सत्यापित कर सकते हैं कि जमाकर्ता का uid दस्तावेज़ के समान ही है जिसे वे लिख रहे हैं। आप सभी को उपस्थित लोगों की सूची पढ़ने की अनुमति देंगे (क्योंकि वहां कोई निजी डेटा नहीं है), लेकिन केवल निर्माता ही इसे अपडेट करने में सक्षम होना चाहिए।

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId;
    }
  }
}

सत्यापन नियम जोड़ें

यह सुनिश्चित करने के लिए डेटा सत्यापन जोड़ें कि दस्तावेज़ में सभी अपेक्षित फ़ील्ड मौजूद हैं:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ... //
    match /attendees/{userId} {
      allow read: if true;
      allow write: if request.auth.uid == userId
          && "attending" in request.resource.data;

    }
  }
}

(वैकल्पिक) अब आप बटन क्लिक करने के परिणाम देख सकते हैं। Firebase कंसोल में अपने Cloud Firestore डैशबोर्ड पर जाएं।

ऐप पूर्वावलोकन

10. बधाई!

आपने इंटरैक्टिव, रीयल-टाइम वेब एप्लिकेशन बनाने के लिए Firebase का उपयोग किया है!

हमने क्या कवर किया है

  • फायरबेस प्रमाणीकरण
  • क्लाउड फायरस्टोर
  • फायरबेस सुरक्षा नियम

अगले कदम

  • अन्य Firebase उत्पादों के बारे में अधिक जानना चाहते हैं? हो सकता है कि आप उन छवि फ़ाइलों को संग्रहीत करना चाहते हैं जिन्हें उपयोगकर्ता अपलोड करते हैं? या अपने उपयोगकर्ताओं को सूचनाएं भेजें? फायरबेस दस्तावेज देखें। फायरबेस के लिए स्पंदन प्लगइन्स के बारे में अधिक जानना चाहते हैं? अधिक जानकारी के लिए FlutterFire देखें।
  • क्लाउड फायरस्टोर के बारे में अधिक जानना चाहते हैं? शायद आप उपसंग्रह और लेन-देन के बारे में जानना चाहते हैं? क्लाउड फायरस्टोर पर अधिक गहराई में जाने वाले कोडलैब के लिए क्लाउड फायरस्टोर वेब कोडलैब पर जाएं। या Cloud Firestore को जानने के लिए इस YouTube श्रृंखला को देखें !

और अधिक जानें

यह कैसे हुआ?

हमें आपकी राय जान कर खुशी होगी! कृपया यहां एक (बहुत) संक्षिप्त फॉर्म भरें।