質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.75%

  • JavaScript

    15316questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • JSON

    1064questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

  • React.js

    714questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

  • Firebase

    507questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

firebaseのrealtimeDatabaseのsecurity&rulesについて。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 328

MOTOMUR

score -85

firebaseを用いて、webサイトを動かそうとしていたのですが、
ルールを設定する段階で、問題が発生し、色々な機能が動かなくなってしまいました。

サイトはこちら

ルールの設定はこんな感じです。

{

  "rules": {

    ".read": true,

    "users": {
      ".read": true,   

      "$uid": { 
        ".validate": "newData.hasChildren(['explain','profile_image','title','uid','user','userStar'])",

        "user":{
          ".write": "$uid === auth.uid",
          ".validate": "newData.isString() && newData.val().length <= 15",
        },
        "uid":{
          ".write": "$uid === auth.uid",
          ".validate": "newData.isString() && newData.val() == auth.uid",
        },
        "explain":{
          ".write": "$uid === auth.uid",
          ".validate": "newData.isString() && newData.val().length <= 300",
        },
        "title":{
          ".write": "$uid === auth.uid",
          ".validate": "newData.isString() && newData.val().length <= 20",
        },
        "profile_image":{
          ".write": "$uid === auth.uid",
          ".validate": "newData.isString() && newData.val().matches(/^(ht|f)tp(s?):\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*((0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\'\\/\\\\+&=%\\$#_]*)?$/)"
        },
        "user_posts":{
          "$postsId":{
            ".write": "$uid === auth.uid",
              ".validate":"newData.val() === true"
          }
        },
        "starred_users":{
          "$starredUid":{
            ".write": "$uid === auth.uid",
              ".validate":"newData.val() === true",
          },
        },
        "userStar":{  
                   ".validate":"newData.hasChild('starCount')",
                   "stars":{  
                      "$starUid":{  
                         ".write":"auth.uid == $starUid &&
                      (!data.exists() && newData.exists() &&
                      newData.parent().parent().child('starCount').val() == data.parent().parent().child('starCount').val() + 1
                       ) ||
                      (data.exists() && !newData.exists() &&
                      newData.parent().parent().child('starCount').val() == data.parent().parent().child('starCount').val() - 1
                       )",
                            ".validate": "newData.val() == true"
                      }

                   },
                   "starCount":{
                      ".write":"auth != null",
                      ".validate":"(newData.val() == data.val() + 1 &&  
                  newData.parent().child('stars').child(auth.uid).val() == true &&  
                  !data.parent().child('stars').child(auth.uid).exists()
                 ) ||
                 (newData.val() == data.val() - 1 &&  
                  !newData.parent().child('stars').child(auth.uid).exists() &&  
                  data.parent().child('stars').child(auth.uid).val() == true
                 )"
                   },
                  "$others":{
                     ".validate":false
                  }
                }

        }
      },

    "posts":{
      ".read": true,
      ".write":"auth != null",
      "$post":{
                ".write": "data.exists() ? (newData.child('uid').val() === auth.uid && 
        newData.child('uid').val() === data.child('uid').val()) : 
        newData.child('uid').val() === auth.uid",
                ".validate":"(newData.hasChildren(['author','body','postComment','postId','postStar','title','uid','timestamp']))||
        (newData.hasChildren(['author','body','postComment','postId','postStar','title','uid','timestamp','post_image']))",


          "author":{
          ".write":"newData.parent().child('uid').val() === auth.uid",
          ".validate": "newData.isString() && newData.val().length <= 15",
        },
        "title":{
          ".write":"newData.parent().child('uid').val() === auth.uid",
          ".validate": "newData.isString() && newData.val().length <= 20",
        },
        "body":{
          ".write":"newData.parent().child('uid').val() === auth.uid",
          ".validate": "newData.isString() && newData.val().length <= 300",
        },
        "uid":{
          ".write":"newData.val() === auth.uid",
        },
        "timestamp":{
          ".write":"newData.parent().child('uid').val() === auth.uid",
        },
        "postComment":{
                    ".validate": "newData.hasChild('commentCount')",
          ".write":true,
          "commentCount":{
            ".write":"auth != null",
                     ".validate":"(newData.val() == data.val() + 1) ||(newData.val() == data.val() - 1)"
          },
            "comments":{
              "$commentId":{
               ".write":"auth != null &&
                      ((!data.exists() && newData.exists() && newData.child('uid').val() === auth.uid &&
                      newData.parent().parent().child('commentCount').val() == data.parent().parent().child('commentCount').val() + 1
                       ) ||
                      (data.exists() && !newData.exists() &&
                      newData.parent().parent().child('commentCount').val() == data.parent().parent().child('commentCount').val() - 1
                       ))",
                            ".validate": "newData.val() == true"
            }
            },
          "$others": {
                        ".write": false
                    } 
          },
        "postId":{
          ".write": "$post === newData.val()",
        },
        "postStar":{
          ".write": "newData.val() === data.val() + 1",
        },
        },
    },

    "comments":{
      ".read": true,
      ".write":true,

      "$comment":{
        ".write": "newData.child('uid').val() === auth.uid",
        ".validate": "newData.hasChildren(['author','body','commentId','uid','profile_image'])",

      }
    },


    "$others": {
            ".validate": false
        }


  }


}

サイトを見てもらうとどのようなサイトかわかると思うのですが、軽いSNSサイトのようなものです。投稿したりフォローしたりコメントしたり。

現在このルールのpostsのどこかのルールを通過できず投稿ができません。また、commentもpost内のcommentsにコメントIDを付加できず怪しい状態です。

ルールの設定に詳しい方、もしくは解決できそうな方、回答お願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ルールがてんこ盛りでこんがらがってしまいますね,お疲れ様です.

まずは,ウェブコンソール上の便利な確認ツールを使ってみましょう.
realtime databaseの「ルール」タブを押すと,右上に「シミュレータ」ボタンがあるはずです.
postsの保存先に適当な形式でpostさせてみましょう.
これを使えば,どのルールを通過出来なかったか分かると思います.

それから(解決してからの話ですが),今後はBolt Compilerの利用を検討してもいいかもしれません.
コメントや型の定義などできて便利です.
Firebase Boltでセキュリティルールを記述する
 

Firebase Japan User Group
https://firebase.asia/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/17 00:49

    丁寧な回答ありがとうございます。

    >「シミュレータ」ボタンがあるはずです
    なぜか僕のプロジェクトでシミュレートをすると、どこでfalseとなったかという詳細が出てこないんですよね 汗
    それで余計に困惑していて、なかなかデバックできない状況です。

    バージョンとかあるのでしょうかね?普通にfirebaseのコンソールから行なっているんですけどね。


    >Bolt Compilerの利用を検討してもいいかもしれません
    firebase上でのルール設定より細かくでき、簡単にできるツールとして捉えて大丈夫でしょうか?
    これの出力をfirebaseのルールにコピペする感じですかね??
    Qiitaの参考でくださった記事だと少し自分の理解力では例が足りないので、もう少し自分で探しても見ようと思うのですが、他に詳しいページにもし精通しておりましたら、教えていただけると嬉しいです。

    キャンセル

  • 2017/11/17 14:52

    入れようとしているデータの構造を間違っていたりしませんか?
    例えば`foo/bar/baz`に`"someUID":"true"`と入れるべきところを,`foo/bar`に`"baz":"true"`と入れてしまっている,など.
    この場合はOKもNGも詳細が出ません.

    > firebase上でのルール設定より細かくでき、簡単にできるツールとして捉えて大丈夫でしょうか?
    細かくはならない(出力するものは普通のルールなので)ですが,簡単にというのは概ねあっていると思います(正確には,大規模でも迷走しにくい).

    > これの出力をfirebaseのルールにコピペする感じですかね??
    それでいけます.
    詳しいページは,公式をGoogle翻訳するのが一番です(Chromeならページ内を右クリック).
    使い方も掲載されてます.

    キャンセル

  • 2017/11/17 18:57

    データ構造の問題の場合はそうなるのですね。たぶんそれが原因だと思います。ありがとうございます。

    頑張って直して、使えそうだったらBolt導入検討しますね!ありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    15316questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • JSON

    1064questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

  • React.js

    714questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

  • Firebase

    507questions

    Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。