Skip to main content

第5章:Rules言語の基本②(request / resource / 変更差分)🔍🛡️✨

この章のテーマはこれ👇 **「今あるデータ(resource)と、これから書き込まれようとしてるデータ(request.resource)を区別して、更新の“差分”で安全に制御する」**です😆💡


1) まずは超重要3点セットを覚える📌😺

Resource vs Request.Resource

✅ resource(今DBにある“既存データ”)

  • resource対象ドキュメントそのもの
  • resource.dataドキュメントの中身(Map) (Firebase)
  • resource.idドキュメントID (Firebase)

✅ request(リクエストの情報)

Request Object Anatomy

  • request.method は操作の種類(get/list/create/update/delete) (Firebase)
  • request.time はサーバーが受け取った時刻(サーバー時刻チェックに使える) (Firebase)

✅ request.resource(“書き込まれた後”の新しい姿)✨

  • request.resource書き込み系(create/update/delete)で使える「新しいresource」 (Firebase)

  • ルールを書くときの感覚はこう👇

    • resource.data = “変更前”
    • request.resource.data = “変更後(こうしたい!)”

2) create / update / delete で「見えるもの」が違う⚠️🧠

Data Visibility by Operation

ここ、事故りやすいので丁寧にいくよ〜😊

🟦 create(新規作成)

  • だいたい resource(既存)が無い(まだ作られてないから)
  • なので 入力検証は request.resource.data が主役

🟨 update(更新)

  • resource.data(変更前)も request.resource.data(変更後)も両方ある
  • “差分”で制御できるから、ここが一番テクい&強い💪🔥

🟥 delete(削除)

  • 削除は クライアントから「新しいデータ」が送られてこないので、request.resource.data を使ったバリデーションができない(=できても意味が薄い)ことが多いよ、という注意が広く共有されてる⚠️ (Qiita)
  • 削除時に見るべきは基本 resource.data(消される側の既存データ) 👀

3) “差分”を取る最強ワザ:Map.diff() 🧩✨

Map Diff Logic

Firestore Rules では Map同士の差分が取れるよ! request.resource.data.diff(resource.data) みたいに書くと、MapDiff が返る💡 (The Firebase Blog)

MapDiff にはこういう便利メソッドがある👇 (Firebase)

  • changedKeys():値が変わったキー
  • addedKeys():追加されたキー
  • removedKeys():消されたキー
  • affectedKeys():追加/変更/削除の全部入り(影響を受けたキー)

4) 手を動かす🧑‍💻🔥:更新で“触っていいフィールドだけ”許す

ここでは例として posts/{postId} を守るよ📮✨ 「本文は編集OK。でも ownerIdcreatedAt は絶対いじれない」みたいなやつ!

4-1. まずはサンプルデータ設計(イメージ)🧠🧱

  • ownerId(投稿者の uid)
  • title(タイトル)
  • body(本文)
  • createdAt(作成時刻)
  • updatedAt(更新時刻)
  • isLocked(ロック中フラグ:trueなら編集不可)

4-2. ルールを書いてみる(差分で update を縛る)🔒✍️

Secure Update Filtering

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

match /posts/{postId} {

// ✅ create: 必須フィールドが揃っていること(例)
allow create: if
request.auth != null
&& request.resource.data.ownerId == request.auth.uid
&& request.resource.data.title is string
&& request.resource.data.body is string
&& request.resource.data.createdAt == request.time
&& request.resource.data.updatedAt == request.time;

// ✅ update: ロック中はダメ + 変更できるキーを限定
allow update: if
request.auth != null
&& resource.data.ownerId == request.auth.uid
&& resource.data.isLocked != true
// 変更して良いのは title, body, updatedAt だけ!
&& request.resource.data.diff(resource.data)
.affectedKeys()
.hasOnly(["title", "body", "updatedAt"].toSet())
// updatedAt はサーバー時刻で更新されていること
&& request.resource.data.updatedAt == request.time;

// ✅ delete: 基本は resource 側の情報で判断
allow delete: if
request.auth != null
&& resource.data.ownerId == request.auth.uid
&& resource.data.isLocked != true;
}
}
}

ポイント解説だよ😊👇

Update Validation Checklist

  • request.resource.data.diff(resource.data).affectedKeys() で「変えたキーの集合」を取る (Firebase)
  • hasOnly(...) で「このキー以外は絶対変えるな!」ができる✨ (The Firebase Blog)
  • request.time を使うと「時刻を勝手に書き換える」系を防ぎやすい⌚ (Firebase)

5) すぐ試す(超かんたん検証)🧪😺

✅ 試す操作(頭の中でOK→できればEmulatorで)

  1. createtitle/body/createdAt/updatedAt を入れて作る → 通る🙆‍♂️
  2. updatetitle だけ変更 + updatedAt=request.time → 通る🙆‍♂️
  3. updateownerId を自分→他人に変えようとする → 弾かれる🙅‍♂️💥
  4. updateisLocked を勝手に false にする → 弾かれる🙅‍♂️💥
  5. deleteisLocked=true の投稿を消す → 弾かれる🙅‍♂️💥

6) ミニ課題🎯🧠(更新時だけ禁止するルールを作ろう)

次の仕様を満たす notes/{noteId} を守ってね📝✨

  • create:ログインしてたらOK
  • update:完全に禁止(編集させない)🚫
  • delete:本人だけOK(owner一致)🗑️

ヒント:allow update: if false; でもOKだよ😂(ルールは正義)


7) チェック✅(ここ答えられたら勝ち!🏆🎉)

  • resource.datarequest.resource.data の違いを、1行で言える?🙂
  • update のとき、“差分”で守ると何が嬉しい?(改造クライアント対策✨)
  • delete で request.resource.data を前提にすると危ない理由、説明できる? (Qiita)

8) AI活用コーナー🤖✨(Rulesづくりを爆速にする)

8-1. “叩き台”はAI、決定は人間🧑‍⚖️✅

AI Rules Drafting & Human Review

Firebase の AIプロンプトカタログには、Rules作成用のプロンプトが用意されてるよ📚✨ しかも Antigravity / Gemini CLI などのエージェント向けに使える前提で整備されてる! (Firebase)

その中の「Security Rulesを書かせる」プロンプトは、**プロジェクト状態を元に1回生成する(自動追従ではない)**と明記されてるので、運用の注意点もバッチリ👌 (Firebase)


8-2. Antigravity × Firebase MCP で「今の設計」を見ながら相談🧠🔧

Firebase MCP サーバーを Antigravity に入れる導線が公式に用意されてるよ(設定手順も公開) (Firebase) 背景として、Firebase側も Antigravity や Gemini CLI で MCP をうまく動かす話をブログで出してる📣 (The Firebase Blog)

**この章の使い方(おすすめ)**👇

  • AIに「posts の update で変更できるキーを title/body/updatedAt に限定したい。Rulesを書いて」って叩き台を作らせる

  • 出てきたRulesに対して、人間がチェックする✅

    • “ownerId 変えられない?”
    • “isLocked を解除できない?”
    • “updatedAt を request.time で縛ってる?”

9) この章のまとめ📦✨

  • resource.data今あるデータrequest.resource.data変更後のデータ (Firebase)
  • update は 差分(diff)で守ると最強🛡️✨ (The Firebase Blog)
  • delete は 基本 resource 側で判断(送信データ前提にしない)⚠️ (Qiita)
  • AIはRules作りを速くするけど、最終レビューは人間🧑‍⚖️✅ (Firebase)

次の章(第6章)に行くと、ここで触れた request.auth を「ログイン必須の守り」に育てていくよ🔐😆