1. بررسی اجمالی
اهداف
در این کد لبه شما یک برنامه توصیه رستوران در اندروید با پشتیبانی Cloud Firestore میسازید. شما یاد خواهید گرفت که چگونه:
- خواندن و نوشتن داده ها در Firestore از یک برنامه Android
- به تغییرات داده های Firestore در زمان واقعی گوش دهید
- از Firebase Authentication و قوانین امنیتی برای ایمن سازی داده های Firestore استفاده کنید
- پرس و جوهای پیچیده Firestore را بنویسید
پیش نیازها
قبل از شروع این کد لبه مطمئن شوید که:
- Android Studio نسخه 4.0 یا بالاتر
- شبیه ساز اندروید با API 19 یا بالاتر
- Node.js نسخه 10 یا بالاتر
- جاوا نسخه 8 یا بالاتر
2. یک پروژه Firebase ایجاد کنید
- با حساب Google خود وارد کنسول Firebase شوید.
- در کنسول Firebase ، روی افزودن پروژه کلیک کنید.
- همانطور که در تصویر زیر نشان داده شده است، یک نام برای پروژه Firebase خود وارد کنید (به عنوان مثال، "Friendly Eats") و روی Continue کلیک کنید.
- ممکن است از شما خواسته شود که Google Analytics را فعال کنید، برای اهداف این کد کد، انتخاب شما مهم نیست.
- پس از یک دقیقه یا بیشتر، پروژه Firebase شما آماده خواهد شد. روی Continue کلیک کنید.
3. پروژه نمونه را راه اندازی کنید
کد را دانلود کنید
دستور زیر را برای کلون کردن کد نمونه برای این Codelab اجرا کنید. با این کار یک پوشه به نام friendlyeats-android
در دستگاه شما ایجاد می شود:
$ git clone https://github.com/firebase/friendlyeats-android
اگر git روی دستگاه خود ندارید، می توانید کد را مستقیماً از GitHub نیز دانلود کنید.
پیکربندی Firebase را اضافه کنید
- در کنسول Firebase ، نمای کلی پروژه را در ناوبری سمت چپ انتخاب کنید. برای انتخاب پلتفرم روی دکمه اندروید کلیک کنید. وقتی نام بسته از شما خواسته شد از
com.google.firebase.example.fireeats
استفاده کنید
- روی ثبت برنامه کلیک کنید و دستورالعمل ها را برای دانلود فایل
google-services.json
دنبال کنید و آن را بهapp/
پوشه کدی که تازه دانلود کرده اید منتقل کنید. سپس روی Next کلیک کنید.
پروژه را وارد کنید
اندروید استودیو را باز کنید. روی File > New > Import Project کلیک کنید و پوشه friendlyeats-android را انتخاب کنید.
4. شبیه سازهای Firebase را راه اندازی کنید
در این کد لبه از مجموعه شبیه ساز Firebase برای شبیه سازی محلی Cloud Firestore و سایر سرویس های Firebase استفاده خواهید کرد. این یک محیط توسعه محلی امن، سریع و بدون هزینه برای ساخت برنامه شما فراهم می کند.
Firebase CLI را نصب کنید
ابتدا باید Firebase CLI را نصب کنید. اگر از macOS یا Linux استفاده می کنید، می توانید دستور cURL زیر را اجرا کنید:
curl -sL https://firebase.tools | bash
اگر از ویندوز استفاده میکنید، دستورالعملهای نصب را بخوانید تا یک باینری مستقل دریافت کنید یا از طریق npm
نصب کنید.
پس از نصب CLI، اجرای firebase --version
باید نسخه 9.0.0
یا بالاتر را گزارش کند:
$ firebase --version 9.0.0
وارد شدن
برای اتصال CLI به حساب Google خود، firebase login
را اجرا کنید. با این کار یک پنجره مرورگر جدید برای تکمیل فرآیند ورود باز می شود. مطمئن شوید که همان حسابی را انتخاب کنید که قبلاً هنگام ایجاد پروژه Firebase خود استفاده می کردید.
پروژه خود را پیوند دهید
از داخل پوشه friendeats friendlyeats-android
، firebase use --add
را اجرا کنید تا پروژه محلی خود را به پروژه Firebase متصل کنید. دستورات را دنبال کنید تا پروژه ای را که قبلا ایجاد کرده اید انتخاب کنید و اگر از شما خواسته شد نام مستعار را انتخاب کنید، default
را وارد کنید.
5. برنامه را اجرا کنید
اکنون زمان اجرای Firebase Emulator Suite و اپلیکیشن اندروید FriendlyEats برای اولین بار است.
شبیه سازها را اجرا کنید
در ترمینال خود از داخل دایرکتوری friendlyeats-android
، firebase emulators:start
به راه اندازی شبیه سازهای Firebase کنید. شما باید گزارش هایی مانند این را ببینید:
$ firebase emulators:start i emulators: Starting emulators: auth, firestore i firestore: Firestore Emulator logging to firestore-debug.log i ui: Emulator UI logging to ui-debug.log ┌─────────────────────────────────────────────────────────────┐ │ ✔ All emulators ready! It is now safe to connect your app. │ │ i View Emulator UI at http://localhost:4000 │ └─────────────────────────────────────────────────────────────┘ ┌────────────────┬────────────────┬─────────────────────────────────┐ │ Emulator │ Host:Port │ View in Emulator UI │ ├────────────────┼────────────────┼─────────────────────────────────┤ │ Authentication │ localhost:9099 │ http://localhost:4000/auth │ ├────────────────┼────────────────┼─────────────────────────────────┤ │ Firestore │ localhost:8080 │ http://localhost:4000/firestore │ └────────────────┴────────────────┴─────────────────────────────────┘ Emulator Hub running at localhost:4400 Other reserved ports: 4500 Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
شما اکنون یک محیط توسعه محلی کامل در حال اجرا بر روی دستگاه خود دارید! مطمئن شوید که این دستور را برای بقیه قسمتهای Codelab اجرا میکنید، برنامه اندروید شما باید به شبیهسازها متصل شود.
برنامه را به شبیه سازها وصل کنید
فایل FirebaseUtil.java
را در Android Studio باز کنید. این فایل حاوی منطق اتصال Firebase SDK به شبیه سازهای محلی در حال اجرا در دستگاه شما است.
در بالای فایل، این خط را بررسی کنید:
/** Use emulators only in debug builds **/
private static final boolean sUseEmulators = BuildConfig.DEBUG;
ما از BuildConfig
استفاده می کنیم تا مطمئن شویم فقط زمانی که برنامه ما در حالت debug
اجرا می شود به شبیه سازها متصل می شویم. وقتی برنامه را در حالت release
کامپایل می کنیم، این شرط نادرست خواهد بود.
حال نگاهی به getFirestore()
:
public static FirebaseFirestore getFirestore() {
if (FIRESTORE == null) {
FIRESTORE = FirebaseFirestore.getInstance();
// Connect to the Cloud Firestore emulator when appropriate. The host '10.0.2.2' is a
// special IP address to let the Android emulator connect to 'localhost'.
if (sUseEmulators) {
FIRESTORE.useEmulator("10.0.2.2", 8080);
}
}
return FIRESTORE;
}
می بینیم که از روش useEmulator(host, port)
برای اتصال Firebase SDK به شبیه ساز محلی Firestore استفاده می کند. در سرتاسر برنامه از FirebaseUtil.getFirestore()
برای دسترسی به این نمونه از FirebaseFirestore
استفاده میکنیم، بنابراین مطمئن هستیم که همیشه هنگام اجرای در حالت debug
به شبیهساز Firestore متصل میشویم.
برنامه را اجرا کنید
اگر فایل google-services.json
را به درستی اضافه کرده اید، اکنون پروژه باید کامپایل شود. در Android Studio روی Build > Rebuild Project کلیک کنید و مطمئن شوید که هیچ خطایی باقی نمانده است.
در اندروید استودیو برنامه را روی شبیه ساز اندروید خود اجرا کنید. در ابتدا با صفحه "ورود به سیستم" نمایش داده می شود. برای ورود به برنامه می توانید از هر ایمیل و رمز عبوری استفاده کنید. این فرآیند ورود به سیستم در حال اتصال به شبیه ساز Firebase Authentication است، بنابراین هیچ اعتبار واقعی منتقل نمی شود.
اکنون رابط کاربری Emulators را با رفتن به http://localhost:4000 در مرورگر وب خود باز کنید. سپس بر روی تب Authentication کلیک کنید و باید حسابی را که ایجاد کرده اید مشاهده کنید:
پس از تکمیل فرآیند ورود، باید صفحه اصلی برنامه را ببینید:
به زودی مقداری داده برای پر کردن صفحه اصلی اضافه خواهیم کرد.
6. داده ها را در Firestore بنویسید
در این بخش داده هایی را در Firestore می نویسیم تا بتوانیم صفحه اصلی خالی فعلی را پر کنیم.
شی مدل اصلی در برنامه ما یک رستوران است (به model/Restaurant.java
مراجعه کنید). داده های Firestore به اسناد، مجموعه ها و زیر مجموعه ها تقسیم می شوند. ما هر رستوران را به عنوان یک سند در یک مجموعه سطح بالا به نام "restaurants"
ذخیره خواهیم کرد. برای کسب اطلاعات بیشتر در مورد مدل داده Firestore، اسناد و مجموعهها را در اسناد مطالعه کنید.
برای اهداف نمایشی، وقتی روی دکمه "افزودن موارد تصادفی" در منوی سرریز کلیک می کنیم، عملکردی را به برنامه اضافه می کنیم تا ده رستوران تصادفی ایجاد کنیم. فایل MainActivity.java
را باز کنید و محتوای onAddItemsClicked()
را با:
private void onAddItemsClicked() {
// Get a reference to the restaurants collection
CollectionReference restaurants = mFirestore.collection("restaurants");
for (int i = 0; i < 10; i++) {
// Get a random Restaurant POJO
Restaurant restaurant = RestaurantUtil.getRandom(this);
// Add a new document to the restaurants collection
restaurants.add(restaurant);
}
}
چند نکته مهم در مورد کد بالا وجود دارد:
- ما با ارجاع به مجموعه
"restaurants"
شروع کردیم. وقتی اسناد اضافه می شوند، مجموعه ها به طور ضمنی ایجاد می شوند، بنابراین نیازی به ایجاد مجموعه قبل از نوشتن داده ها نیست. - اسناد را می توان با استفاده از POJOs (Plain Old Java Object) ایجاد کرد، که ما از آن برای ایجاد هر سند رستوران استفاده می کنیم.
- متد
add()
سندی را با یک شناسه تولید خودکار به مجموعه اضافه می کند، بنابراین نیازی به تعیین شناسه منحصر به فرد برای هر رستوران نداریم.
اکنون برنامه را دوباره اجرا کنید و روی دکمه "افزودن موارد تصادفی" در منوی سرریز (در گوشه سمت راست بالا) کلیک کنید تا کدی را که نوشتید فراخوانی کنید:
اکنون رابط کاربری Emulators را با رفتن به http://localhost:4000 در مرورگر وب خود باز کنید. سپس بر روی تب Firestore کلیک کنید و باید داده هایی را که به تازگی اضافه کرده اید مشاهده کنید:
این داده ها 100% محلی برای دستگاه شما هستند. در واقع، پروژه واقعی شما هنوز حاوی پایگاه داده Firestore نیست! این بدان معناست که آزمایش با تغییر و حذف این دادهها بدون عواقب بیخطر است.
تبریک میگوییم، شما فقط دادهها را به Firestore نوشتید! در مرحله بعدی نحوه نمایش این داده ها را در برنامه یاد خواهیم گرفت.
7. نمایش داده ها از Firestore
در این مرحله یاد می گیریم که چگونه داده ها را از Firestore بازیابی کرده و در برنامه خود نمایش دهیم. اولین قدم برای خواندن داده ها از Firestore ایجاد یک Query
است. فایل MainActivity.java
را باز کنید و کد زیر را به ابتدای onCreate()
اضافه کنید:
mFirestore = FirebaseUtil.getFirestore();
// Get the 50 highest rated restaurants
mQuery = mFirestore.collection("restaurants")
.orderBy("avgRating", Query.Direction.DESCENDING)
.limit(LIMIT);
اکنون می خواهیم به پرس و جو گوش دهیم تا همه اسناد مطابق را دریافت کنیم و از به روز رسانی های آینده در زمان واقعی مطلع شویم. از آنجا که هدف نهایی ما اتصال این داده ها به RecyclerView
است، باید یک کلاس RecyclerView.Adapter
ایجاد کنیم تا به داده ها گوش دهیم.
کلاس FirestoreAdapter
را که قبلاً تا حدی پیاده سازی شده است باز کنید. ابتدا، اجازه دهید آداپتور onEvent
EventListener
تعریف کنیم تا بتواند بهروزرسانیهای یک Query Firestore را دریافت کند:
public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH>
implements EventListener<QuerySnapshot> { // Add this "implements"
// ...
// Add this method
@Override
public void onEvent(QuerySnapshot documentSnapshots,
FirebaseFirestoreException e) {
// Handle errors
if (e != null) {
Log.w(TAG, "onEvent:error", e);
return;
}
// Dispatch the event
for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
// Snapshot of the changed document
DocumentSnapshot snapshot = change.getDocument();
switch (change.getType()) {
case ADDED:
// TODO: handle document added
break;
case MODIFIED:
// TODO: handle document modified
break;
case REMOVED:
// TODO: handle document removed
break;
}
}
onDataChanged();
}
// ...
}
در بارگذاری اولیه شنونده یک رویداد ADDED
برای هر سند جدید دریافت می کند. از آنجایی که مجموعه نتیجه پرس و جو در طول زمان تغییر می کند، شنونده رویدادهای بیشتری حاوی تغییرات را دریافت خواهد کرد. حالا بیایید اجرای شنونده را به پایان برسانیم. ابتدا سه روش جدید اضافه کنید: onDocumentAdded
، onDocumentModified
و onDocumentRemoved
:
protected void onDocumentAdded(DocumentChange change) {
mSnapshots.add(change.getNewIndex(), change.getDocument());
notifyItemInserted(change.getNewIndex());
}
protected void onDocumentModified(DocumentChange change) {
if (change.getOldIndex() == change.getNewIndex()) {
// Item changed but remained in same position
mSnapshots.set(change.getOldIndex(), change.getDocument());
notifyItemChanged(change.getOldIndex());
} else {
// Item changed and changed position
mSnapshots.remove(change.getOldIndex());
mSnapshots.add(change.getNewIndex(), change.getDocument());
notifyItemMoved(change.getOldIndex(), change.getNewIndex());
}
}
protected void onDocumentRemoved(DocumentChange change) {
mSnapshots.remove(change.getOldIndex());
notifyItemRemoved(change.getOldIndex());
}
سپس این متدهای جدید را از onEvent
:
@Override
public void onEvent(QuerySnapshot documentSnapshots,
FirebaseFirestoreException e) {
// ...
// Dispatch the event
for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
// Snapshot of the changed document
DocumentSnapshot snapshot = change.getDocument();
switch (change.getType()) {
case ADDED:
onDocumentAdded(change); // Add this line
break;
case MODIFIED:
onDocumentModified(change); // Add this line
break;
case REMOVED:
onDocumentRemoved(change); // Add this line
break;
}
}
onDataChanged();
}
در نهایت startListening()
را برای پیوست کردن شنونده پیاده سازی کنید:
public void startListening() {
if (mQuery != null && mRegistration == null) {
mRegistration = mQuery.addSnapshotListener(this);
}
}
اکنون برنامه به طور کامل برای خواندن داده ها از Firestore پیکربندی شده است. برنامه را دوباره اجرا کنید و باید رستوران هایی را که در مرحله قبل اضافه کرده اید ببینید:
اکنون به رابط کاربری Emulator در مرورگر خود برگردید و یکی از نامهای رستوران را ویرایش کنید. شما باید تغییر آن را در برنامه تقریباً بلافاصله مشاهده کنید!
8. مرتب سازی و فیلتر کردن داده ها
این برنامه در حال حاضر بهترین رستوران ها را در کل مجموعه نمایش می دهد، اما در یک برنامه رستوران واقعی کاربر می خواهد داده ها را مرتب کرده و فیلتر کند. به عنوان مثال، برنامه باید بتواند "رستوران های برتر غذاهای دریایی در فیلادلفیا" یا "کم هزینه ترین پیتزا" را نشان دهد.
با کلیک بر روی نوار سفید در بالای برنامه، یک گفتگوی فیلترها ظاهر می شود. در این بخش از پرس و جوهای Firestore برای کارکرد این گفتگو استفاده می کنیم:
بیایید onFilter()
MainActivity.java
را ویرایش کنیم. این روش یک شی Filters
را می پذیرد که یک شی کمکی است که ما برای گرفتن خروجی گفتگوی فیلترها ایجاد کرده ایم. ما این روش را برای ساخت یک پرس و جو از فیلترها تغییر می دهیم:
@Override
public void onFilter(Filters filters) {
// Construct basic query
Query query = mFirestore.collection("restaurants");
// Category (equality filter)
if (filters.hasCategory()) {
query = query.whereEqualTo("category", filters.getCategory());
}
// City (equality filter)
if (filters.hasCity()) {
query = query.whereEqualTo("city", filters.getCity());
}
// Price (equality filter)
if (filters.hasPrice()) {
query = query.whereEqualTo("price", filters.getPrice());
}
// Sort by (orderBy with direction)
if (filters.hasSortBy()) {
query = query.orderBy(filters.getSortBy(), filters.getSortDirection());
}
// Limit items
query = query.limit(LIMIT);
// Update the query
mQuery = query;
mAdapter.setQuery(query);
// Set header
mCurrentSearchView.setText(Html.fromHtml(filters.getSearchDescription(this)));
mCurrentSortByView.setText(filters.getOrderDescription(this));
// Save filters
mViewModel.setFilters(filters);
}
در قطعه بالا، یک شی Query
با where
کردن عبارتهای Where و orderBy
برای مطابقت با فیلترهای داده شده ایجاد میکنیم.
برنامه را دوباره اجرا کنید و فیلتر زیر را برای نمایش محبوب ترین رستوران های ارزان قیمت انتخاب کنید:
اکنون باید یک لیست فیلتر شده از رستوران ها را مشاهده کنید که فقط شامل گزینه های ارزان قیمت است:
اگر تا اینجا پیش رفته اید، اکنون یک برنامه مشاهده توصیه رستوران کاملاً کارآمد در Firestore ساخته اید! اکنون می توانید رستوران ها را در زمان واقعی مرتب و فیلتر کنید. در چند بخش بعدی نظراتی را به رستوران ها اضافه می کنیم و قوانین امنیتی را به برنامه اضافه می کنیم.
9. داده ها را در زیر مجموعه ها سازماندهی کنید
در این بخش رتبهبندیهایی را به برنامه اضافه میکنیم تا کاربران بتوانند رستورانهای مورد علاقه (یا حداقل مورد علاقه) خود را بررسی کنند.
مجموعه ها و زیر مجموعه ها
تا کنون ما تمام داده های رستوران را در یک مجموعه سطح بالا به نام "رستوران" ذخیره کرده ایم. وقتی کاربر به یک رستوران امتیاز می دهد، می خواهیم یک شی Rating
جدید به رستوران ها اضافه کنیم. برای این کار از یک زیر مجموعه استفاده می کنیم. شما می توانید یک زیر مجموعه را به عنوان مجموعه ای در نظر بگیرید که به یک سند پیوست شده است. بنابراین هر سند رستوران یک زیرمجموعه رتبه بندی پر از اسناد رتبه بندی خواهد داشت. مجموعههای فرعی به سازماندهی دادهها کمک میکنند بدون اینکه اسناد ما را متورم کند یا نیاز به جستجوهای پیچیده داشته باشد.
برای دسترسی به یک زیر مجموعه، .collection()
را در سند والد فراخوانی کنید:
CollectionReference subRef = mFirestore.collection("restaurants")
.document("abc123")
.collection("ratings");
شما میتوانید مانند مجموعههای سطح بالا به یک زیرمجموعه دسترسی داشته باشید و آن را جستجو کنید، هیچ محدودیت اندازه یا تغییر عملکرد وجود ندارد. در اینجا می توانید اطلاعات بیشتری در مورد مدل داده Firestore بخوانید .
نوشتن داده ها در یک تراکنش
افزودن یک Rating
به زیر مجموعه مناسب فقط نیازمند فراخوانی .add()
است، اما همچنین باید میانگین رتبهبندی شی Restaurant
و تعداد رتبهبندیها را بهروزرسانی کنیم تا دادههای جدید را منعکس کنیم. اگر از عملیات جداگانه برای ایجاد این دو تغییر استفاده کنیم، تعدادی شرایط مسابقه وجود دارد که می تواند منجر به داده های قدیمی یا نادرست شود.
برای اطمینان از اینکه رتبهبندیها به درستی اضافه میشوند، از تراکنش برای افزودن رتبهبندی به رستوران استفاده میکنیم. این تراکنش چند عمل انجام می دهد:
- رتبه فعلی رستوران را بخوانید و امتیاز جدید را محاسبه کنید
- امتیاز را به زیر مجموعه اضافه کنید
- میانگین رتبهبندی و تعداد رتبهبندی رستوران را بهروزرسانی کنید
RestaurantDetailActivity.java
را باز کنید و تابع addRating
را پیاده سازی کنید:
private Task<Void> addRating(final DocumentReference restaurantRef,
final Rating rating) {
// Create reference for new rating, for use inside the transaction
final DocumentReference ratingRef = restaurantRef.collection("ratings")
.document();
// In a transaction, add the new rating and update the aggregate totals
return mFirestore.runTransaction(new Transaction.Function<Void>() {
@Override
public Void apply(Transaction transaction)
throws FirebaseFirestoreException {
Restaurant restaurant = transaction.get(restaurantRef)
.toObject(Restaurant.class);
// Compute new number of ratings
int newNumRatings = restaurant.getNumRatings() + 1;
// Compute new average rating
double oldRatingTotal = restaurant.getAvgRating() *
restaurant.getNumRatings();
double newAvgRating = (oldRatingTotal + rating.getRating()) /
newNumRatings;
// Set new restaurant info
restaurant.setNumRatings(newNumRatings);
restaurant.setAvgRating(newAvgRating);
// Commit to Firestore
transaction.set(restaurantRef, restaurant);
transaction.set(ratingRef, rating);
return null;
}
});
}
تابع addRating()
یک Task
را برمی گرداند که کل تراکنش را نشان می دهد. در تابع onRating()
شنوندگان به وظیفه اضافه می شوند تا به نتیجه تراکنش پاسخ دهند.
حالا دوباره برنامه را اجرا کنید و روی یکی از رستوران ها کلیک کنید، که باید صفحه جزئیات رستوران ظاهر شود. برای شروع اضافه کردن نظر، روی دکمه + کلیک کنید. با انتخاب تعدادی ستاره و وارد کردن متن، نظری را اضافه کنید.
با زدن گزینه Submit تراکنش آغاز می شود. وقتی تراکنش کامل شد، نظر خود را در زیر نمایش داده میشود و بهروزرسانی تعداد بازبینی رستوران را مشاهده میکنید:
تبریک میگم اکنون یک برنامه بررسی رستوران اجتماعی، محلی و موبایلی دارید که بر روی Cloud Firestore ساخته شده است. شنیده ام که این روزها بسیار محبوب هستند.
10. داده های خود را ایمن کنید
تاکنون امنیت این اپلیکیشن را در نظر نگرفته ایم. چگونه بفهمیم که کاربران فقط می توانند داده های صحیح خود را بخوانند و بنویسند؟ پایگاه داده های Firestore توسط یک فایل پیکربندی به نام قوانین امنیتی محافظت می شوند.
فایل firestore.rules
را باز کنید، باید موارد زیر را مشاهده کنید:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
//
// WARNING: These rules are insecure! We will replace them with
// more secure rules later in the codelab
//
allow read, write: if request.auth != null;
}
}
}
بیایید این قوانین را تغییر دهیم تا از دسترسی یا تغییرات ناخواسته به داده جلوگیری کنیم، فایل firestore.rules
را باز کرده و محتوا را با موارد زیر جایگزین کنیم:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Determine if the value of the field "key" is the same
// before and after the request.
function isUnchanged(key) {
return (key in resource.data)
&& (key in request.resource.data)
&& (resource.data[key] == request.resource.data[key]);
}
// Restaurants
match /restaurants/{restaurantId} {
// Any signed-in user can read
allow read: if request.auth != null;
// Any signed-in user can create
// WARNING: this rule is for demo purposes only!
allow create: if request.auth != null;
// Updates are allowed if no fields are added and name is unchanged
allow update: if request.auth != null
&& (request.resource.data.keys() == resource.data.keys())
&& isUnchanged("name");
// Deletes are not allowed.
// Note: this is the default, there is no need to explicitly state this.
allow delete: if false;
// Ratings
match /ratings/{ratingId} {
// Any signed-in user can read
allow read: if request.auth != null;
// Any signed-in user can create if their uid matches the document
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid;
// Deletes and updates are not allowed (default)
allow update, delete: if false;
}
}
}
}
این قوانین دسترسی را محدود می کند تا اطمینان حاصل شود که مشتریان فقط تغییرات ایمن ایجاد می کنند. برای مثال، بهروزرسانیهای یک سند رستوران فقط میتواند رتبهبندیها را تغییر دهد، نه نام یا هر داده غیرقابل تغییر دیگری. رتبهبندیها فقط در صورتی ایجاد میشوند که شناسه کاربری با کاربر واردشده مطابقت داشته باشد، که از جعل جلوگیری میکند.
برای مطالعه بیشتر در مورد قوانین امنیتی، به مستندات مراجعه کنید.
11. نتیجه گیری
شما اکنون یک برنامه با امکانات کامل در بالای Firestore ایجاد کرده اید. شما در مورد مهمترین ویژگی های Firestore از جمله:
- اسناد و مجموعه ها
- خواندن و نوشتن داده ها
- مرتب سازی و فیلتر کردن با پرس و جو
- زیر مجموعه ها
- معاملات
بیشتر بدانید
برای ادامه یادگیری در مورد Firestor، در اینجا چند مکان خوب برای شروع وجود دارد:
برنامه رستوران در این کد لبه بر اساس برنامه مثال "Friendly Eats" است. میتوانید کد منبع آن برنامه را در اینجا مرور کنید.
اختیاری: استقرار در تولید
تا کنون این برنامه فقط از Firebase Emulator Suite استفاده کرده است. اگر می خواهید نحوه استقرار این برنامه را در یک پروژه Firebase واقعی بیاموزید، به مرحله بعدی ادامه دهید.
12. (اختیاری) برنامه خود را اجرا کنید
تا کنون این برنامه کاملاً محلی بوده است، همه داده ها در مجموعه شبیه ساز Firebase موجود است. در این بخش یاد خواهید گرفت که چگونه پروژه Firebase خود را پیکربندی کنید تا این برنامه در مرحله تولید کار کند.
احراز هویت Firebase
در کنسول Firebase به بخش Authentication بروید و روی شروع کلیک کنید. به برگه روش ورود به سیستم بروید و گزینه ایمیل/گذرواژه را از ارائه دهندگان بومی انتخاب کنید.
روش ورود به سیستم ایمیل/گذرواژه را فعال کنید و روی ذخیره کلیک کنید.
فایر استور
ایجاد پایگاه داده
به بخش Firestore Database کنسول بروید و روی Create Database کلیک کنید:
- وقتی در مورد قوانین امنیتی از شما خواسته شد که در حالت تولید شروع به کار کنید، به زودی آن قوانین را بهروزرسانی خواهیم کرد.
- مکان پایگاه داده ای را که می خواهید برای برنامه خود استفاده کنید، انتخاب کنید. توجه داشته باشید که انتخاب مکان پایگاه داده یک تصمیم دائمی است و برای تغییر آن باید یک پروژه جدید ایجاد کنید. برای اطلاعات بیشتر در مورد انتخاب محل پروژه، به مستندات مراجعه کنید.
استقرار قوانین
برای استقرار قوانین امنیتی که قبلاً نوشتید، دستور زیر را در پوشه codelab اجرا کنید:
$ firebase deploy --only firestore:rules
این محتویات firestore.rules
را در پروژه شما مستقر می کند، که می توانید با رفتن به تب Rules در کنسول، آن را تأیید کنید.
استقرار شاخص ها
برنامه FriendlyEats مرتبسازی و فیلترینگ پیچیدهای دارد که به تعدادی شاخص ترکیبی سفارشی نیاز دارد. اینها را می توان با دست در کنسول Firebase ایجاد کرد، اما نوشتن تعاریف آنها در فایل firestore.indexes.json
و استقرار آنها با استفاده از Firebase CLI ساده تر است.
اگر فایل firestore.indexes.json
را باز کنید، می بینید که نمایه های مورد نیاز قبلاً ارائه شده است:
{
"indexes": [
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "city", "mode": "ASCENDING" },
{ "fieldPath": "avgRating", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "category", "mode": "ASCENDING" },
{ "fieldPath": "avgRating", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "price", "mode": "ASCENDING" },
{ "fieldPath": "avgRating", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "city", "mode": "ASCENDING" },
{ "fieldPath": "numRatings", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "category", "mode": "ASCENDING" },
{ "fieldPath": "numRatings", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "price", "mode": "ASCENDING" },
{ "fieldPath": "numRatings", "mode": "DESCENDING" }
]
},
{
"collectionId": "restaurants",
"queryScope": "COLLECTION",
"fields": [
{ "fieldPath": "city", "mode": "ASCENDING" },
{ "fieldPath": "price", "mode": "ASCENDING" }
]
},
{
"collectionId": "restaurants",
"fields": [
{ "fieldPath": "category", "mode": "ASCENDING" },
{ "fieldPath": "price", "mode": "ASCENDING" }
]
}
],
"fieldOverrides": []
}
برای استقرار این شاخص ها دستور زیر را اجرا کنید:
$ firebase deploy --only firestore:indexes
توجه داشته باشید که ایجاد ایندکس آنی نیست، می توانید پیشرفت را در کنسول Firebase نظارت کنید.
برنامه را پیکربندی کنید
در کلاس FirebaseUtil
ما Firebase SDK را برای اتصال به شبیه سازها در حالت اشکال زدایی پیکربندی کردیم:
public class FirebaseUtil {
/** Use emulators only in debug builds **/
private static final boolean sUseEmulators = BuildConfig.DEBUG;
// ...
}
اگر می خواهید برنامه خود را با پروژه Firebase واقعی خود آزمایش کنید، می توانید:
- برنامه را در حالت انتشار بسازید و آن را روی دستگاه اجرا کنید.
-
sUseEmulators
را موقتاً بهfalse
تغییر دهید و دوباره برنامه را اجرا کنید.
توجه داشته باشید که ممکن است لازم باشد از برنامه خارج شوید و دوباره وارد شوید تا بتوانید به درستی به تولید وصل شوید.