شروط الكتابة لقواعد أمان Cloud Firestore

يعتمد هذا الدليل على دليل بناء قواعد الأمان لتوضيح كيفية إضافة شروط إلى Cloud Firestore Security Rules. إذا لم تكن على دراية بأساسيات Cloud Firestore Security Rules، يمكنك الاطّلاع على دليل البدء.

الشرط هو الوحدة الأساسية في Cloud Firestore Security Rules. الشرط هو تعبير منطقي يحدّد ما إذا كان يجب السماح بعملية معيّنة أو رفضها. استخدِم قواعد الأمان لكتابة الشروط التي تتحقّق من مصادقة المستخدم أو من صحة البيانات الواردة أو حتى من الوصول إلى أجزاء أخرى من قاعدة بياناتك.

للحصول على مساعدة من الذكاء الاصطناعي، انسخ الطلب أدناه إلى وكيل الترميز بالذكاء الاصطناعي (مثل Gemini في "استوديو Android" وAntigravity وClaude Code وCodex وCursor). يمكنك تخصيص الطلب وتكراره مع الوكيل. انتقِل إلى مهارات وكلاء Firebase للحصول على معلومات مفصّلة عن التثبيت.

Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's Firestore data.

المصادقة

من أكثر أنماط قواعد الأمان شيوعًا التحكّم في الوصول استنادًا إلى حالة مصادقة المستخدم. على سبيل المثال، قد ترغب في أن يسمح تطبيقك للمستخدمين الذين سجّلوا الدخول فقط بكتابة البيانات:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

هناك نمط شائع آخر وهو التأكّد من أنّ المستخدمين يمكنهم قراءة بياناتهم الخاصة وكتابتها فقط:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

إذا كان تطبيقك يستخدم "مصادقة Firebase" أو Google Cloud Identity Platform، يحتوي المتغيّر request.auth على معلومات المصادقة للعميل الذي يطلب البيانات. لمزيد من المعلومات حول "request.auth"، يُرجى الاطّلاع على المستندات المرجعية.

التحقّق من صحة البيانات

تخزّن العديد من التطبيقات معلومات التحكّم في الوصول كحقول في المستندات في قاعدة البيانات. يمكن لـ "Cloud Firestore Security Rules" السماح بالوصول أو رفضه ديناميكيًا استنادًا إلى بيانات المستند:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

يشير المتغيّر resource إلى المستند المطلوب، بينما يشير resource.data إلى خريطة لجميع الحقول والقيم المخزّنة في المستند. لمزيد من المعلومات حول المتغيّر resource، يُرجى الاطّلاع على المستندات المرجعية.

عند كتابة البيانات، قد تحتاج إلى مقارنة البيانات الواردة بالبيانات الحالية. في هذه الحالة، إذا كانت مجموعة القواعد تسمح بعملية الكتابة المعلّقة، يحتوي المتغيّر request.resource على الحالة المستقبلية للمستند. بالنسبة إلى عمليات update التي تعدّل فقط مجموعة فرعية من حقول المستند، سيحتوي المتغيّر request.resource على حالة المستند المعلّقة بعد العملية. يمكنك التحقّق من قيم الحقول في request.resource لمنع تعديلات البيانات غير المرغوب فيها أو غير المتّسقة:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

الوصول إلى مستندات أخرى

باستخدام الدالتَين get() وexists()، يمكن لقواعد الأمان تقييم الطلبات الواردة مقارنةً بالمستندات الأخرى في قاعدة البيانات. تتطلّب الدالتان get() وexists() مسارات مستندات محدّدة بالكامل. عند استخدام المتغيّرات لإنشاء مسارات لـ get() وexists()، عليك استخدام صيغة $(variable) بشكل صريح لتجاوز المتغيّرات.

في المثال أدناه، يتم تسجيل المتغيّر database من خلال عبارة المطابقة match /databases/{database}/documents ويتم استخدامه لتشكيل المسار:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid));

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    }
  }
}

بالنسبة إلى عمليات الكتابة، يمكنك استخدام الدالة getAfter() للوصول إلى حالة مستند بعد اكتمال عملية أو دفعة من عمليات الكتابة ولكن قبل تنفيذ العملية أو الدفعة. مثل get()، تأخذ الدالة getAfter() مسار مستند محدّدًا بالكامل. يمكنك استخدام getAfter() لتحديد مجموعات من عمليات الكتابة التي يجب تنفيذها معًا كعملية أو دفعة.

الوصول إلى حدود المكالمات

هناك حدّ أقصى لطلبات الوصول إلى المستندات لكل تقييم لمجموعة قواعد:

  • ‫10 لطلبات المستندات الفردية وطلبات البحث
  • ‫20 لعمليات قراءة المستندات المتعددة والمعاملات وعمليات الكتابة المجمّعة وينطبق أيضًا الحدّ الأقصى السابق البالغ 10 على كل عملية.

    على سبيل المثال، لنفترض أنّك أنشأت طلب كتابة مجمّعًا يتضمّن 3 عمليات كتابة، وأنّ قواعد الأمان تستخدم طلبَين للوصول إلى المستندات من أجل التحقّق من صحة كل عملية كتابة. في هذه الحالة، تستخدم كل عملية كتابة مكالمتَي وصول من أصل 10 مكالمات، ويستخدم طلب الكتابة المجمّع 6 مكالمات وصول من أصل 20 مكالمة.

ويؤدي تجاوز أي من الحدّين إلى ظهور خطأ "تم رفض الإذن". قد يتم تخزين بعض طلبات الوصول إلى المستندات مؤقتًا، ولا يتم احتساب الطلبات المخزّنة مؤقتًا ضمن الحدود القصوى.

للحصول على شرح مفصّل حول كيفية تأثير هذه الحدود في المعاملات وعمليات الكتابة المجمّعة، يُرجى الاطّلاع على دليل تأمين العمليات الذرية.

الوصول إلى المكالمات والأسعار

يؤدي استخدام هذه الدوال إلى تنفيذ عملية قراءة في قاعدة البيانات، ما يعني أنّه سيتم تحصيل رسوم منك مقابل قراءة المستندات حتى إذا رفضت قواعدك الطلب. يمكنك الاطّلاع على أسعار Rules لمزيد من المعلومات المحدّدة حول الفوترة.

الدوال المخصّصة

عندما تصبح قواعد الأمان أكثر تعقيدًا، قد تحتاج إلى تضمين مجموعات من الشروط في دوال يمكنك إعادة استخدامها في مجموعة القواعد. تتيح قواعد الأمان استخدام الدوال المخصّصة. يشبه بناء جملة الدوال المخصصة إلى حد ما JavaScript، ولكن يتم كتابة دوال قواعد الأمان بلغة خاصة بالمجال ولها بعض القيود المهمة:

  • يمكن أن تحتوي الدوال على عبارة return واحدة فقط. ولا يمكن أن تحتوي على أي منطق إضافي. على سبيل المثال، لا يمكنها تنفيذ حلقات أو استدعاء خدمات خارجية.
  • يمكن للدوال الوصول تلقائيًا إلى الدوال والمتغيرات من النطاق الذي تم تعريفها فيه. على سبيل المثال، يمكن لدالة محدّدة ضمن نطاق service cloud.firestore الوصول إلى المتغيّر resource والدوال المضمّنة، مثل get() وexists().
  • يمكن أن تستدعي الدوال دوال أخرى ولكن لا يمكن أن تتكرر. يقتصر إجمالي عمق حزمة التنفيذ على 10.
  • في الإصدار v2 من القواعد، يمكن للدوال تحديد المتغيّرات باستخدام الكلمة الرئيسية let. يمكن أن تحتوي الدوال على ما يصل إلى 10 عمليات ربط let، ولكن يجب أن تنتهي بعبارة return.

يتم تحديد الدالة باستخدام الكلمة الرئيسية function وتتلقّى صفرًا أو أكثر من الوسيطات. على سبيل المثال، قد ترغب في دمج نوعي الشروط المستخدمة في الأمثلة أعلاه في دالة واحدة:

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

يؤدي استخدام الدوال في قواعد الأمان إلى تسهيل صيانتها مع زيادة تعقيد القواعد.

القواعد ليست فلاتر

بمجرد تأمين بياناتك والبدء في كتابة الاستعلامات، ضع في اعتبارك أن قواعد الأمان ليست عوامل تصفية. لا يمكنك كتابة طلب بحث لجميع المستندات في مجموعة وتوقُّع أن تعرض "القواعد" المستندات التي يملك العميل الحالي إذن الوصول إليها فقط.

على سبيل المثال، لنفترض أنّ قاعدة الأمان التالية:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

مرفوض: ترفض هذه القاعدة طلب البحث التالي لأنّ مجموعة النتائج يمكن أن تتضمّن مستندات لا يكون فيها visibility هو public:

الويب
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

مسموح به: تسمح هذه القاعدة بطلب البحث التالي لأنّ عبارة where("visibility", "==", "public") تضمن أنّ مجموعة النتائج تستوفي شرط القاعدة:

الويب
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

تقيّم قواعد الأمان كل طلب بحث مقابل نتيجته المحتملة، وتُفشل الطلب إذا كان من الممكن أن يعرض مستندًا لا يملك العميل إذنًا بقراءته. يجب أن تتبع طلبات البحث القيود التي تضعها قواعد الأمان. لمزيد من المعلومات حول قواعد الأمان وطلبات البحث، يُرجى الاطّلاع على الاستعلام عن البيانات بشكل آمن.

الخطوات التالية