前置き
前回の続きです。
チャットアプリの作成で
Firebase Realtime Databaseを使用。
グループチャットまではやらず、
単純にアプリ使用者で
1つのチャットルームを
使用しているようなイメージです。
前回のルールでは
公式サンプルを見てログインユーザーのみ
読み書き込みできるようにし、
ルールの理解をしていきました。
実際はチャット機能の実装なので、
書き込みは自分のみ、
読み取りはグループ内の全ユーザーの
メッセージを取得する必要があります🍀
ひとまずreadをtrueにし、
取得の方法を考えていきます❗️
ref('users/').on()
ここに送信されるようになっています。
users/uid/自動生成されたキー
ref('users/').on()に
するとusers
直下のuid
が取得されてしまいます。
取得したいのはuid
以降のオブジェクトです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
export const actions = { async submitChat(_, payload) { try { await this.$fire.database .ref('users/' + payload.uid) .push() .set({ text: payload.text, time: this.$fireModule.database.ServerValue.TIMESTAMP, uid: payload.uid, }) } catch (error) { console.log(error)//eslint-disable-line } }, async getData({ commit }) { try { await this.$fire.database.ref('users/').on('value', (snapshot) => { const data = snapshot.val() console.log(data) }) } catch (error) { console.log(error)//eslint-disable-line } }, } |
ref('users/' + uid).once()
ということでuid
以降を取得する必要があります。
今回はonce()
を使用していますが、on()
と同じです。
データを読み取る
しかしこれだと
自分のデータしか取得できません。uid
、ではなく
ワイルドカードのようなものを
使用する必要がありそうです。
とはいってもそれはFirebase上の話で
コードで当てはまるものがありません。
一応ドキュメントを確認しましたが、
それらしいものが見つけられませんでした。
ちなみに取得データはこのようなオブジェクトです。
{ 自動生成されたキー: { text: ここにメッセージ }}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
export const actions = { async getData({ commit }) { try { const uid = this.$fire.auth.currentUser.uid await this.$fire.database .ref('users/' + uid) .once('value') .then((data) => { console.log(data.val()) }) } catch (error) { console.log(error)//eslint-disable-line } }, } |
ルールの問題
そしてrefを空にしてみた場合
アクセス権がないとエラー。
つまりルールのせいで
取得できていないということですね。
Error: permission_denied at /: Client doesn't have permission to access the desired data.
ルールに階層つけずに
読み書きtrue
に戻し、ref
を空にすると全体のデータが
取得できました❗️
まぁref
が空だとdatabaseのurlになるので
絶対そこのデータが取得できるはずですもんね…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
export const actions = { async getData({ commit }) { try { await this.$fire.database .ref() .once('value') .then((data) => { console.log(data.val()) }) } catch (error) { console.log(error)//eslint-disable-line } }, } |
ルールをまた変更してみます。
1 2 3 4 5 6 7 8 9 10 |
{ "rules": { "users": { "$uid": { ".read": "auth.uid != null", ".write": "$uid === auth.uid", } } } } |
しかしこれでもログインしても権限なし💥
書きはできるのに読みができない💥users/$uid
ではできないので階層を変更。
1 2 3 4 5 6 7 8 9 10 |
{ "rules": { ".read": "true", "users": { "$uid": { ".write": "$uid === auth.uid", } } } } |
ログインしてない場合は
見れないようにする。
1 2 3 4 5 6 7 8 9 10 |
{ "rules": { ".read": "auth != null", "users": { "$uid": { ".write": "auth.uid != null", } } } } |
そうすると
今度はログインしてなくても
全部のデータが見れてしまう🙄💣💥
ルールの意味なし、、、users
の後ろに設定しても意味はなく。。。
方向転換が必要?
ルールと取得のメソッドon()
, once()
, get()
関係があるのかとも思いましたが、
エラー内容が権限なし、
なのでメソッドは
直接的には関係なさそうです。
そもそもデータの形を
users/自動生成されたkey
にしてデータ内のuid
と一致させる方が
良いのかもしれません。
データ構造のおすすめの方法
書き込みと編集は、
Authのuid
と送信されたuid
が
一致している場合にしたかったので
users/uid/自動生成されたキー
にしていましたが、
組み込み変数でやってみようかと検討中。
まとめ
ルールについて書かれた記事を
いくつかパパッと見ましたが、
同じ記述だったので、
何が問題なのかまだ解決できていません。
ルールが変わったのか❓
と思って探しましたが
見当たりませんでした。
潔くやり方を変更予定です🍀