![見出し画像](https://assets.st-note.com/production/uploads/images/54714153/rectangle_large_type_2_f0e65df772868ff23bf4aa95f8e38e70.png?width=800)
【Nuxt.js】Firebase Auth × Cloud Firestore ログインアカウントの送信と取得を考える
🎈 WPでも公開中です
https://wp.me/pc9NHC-1m9
前置き
Udemyのコースで
自分自身も見直して勉強になったので
Firebase関連の
送信・取得をまとめていきます💫
以前も何度かやっていますが、
ulとliでコンポーネントを分けて…
というのがなかったので、
その辺も含めて💡
作ったのはfirebaseと連携した
チャット機能(Realtime Database)と
タスク管理機能(Cloud Firestore)
2画面一緒に見れて
いちいち切り替えなくて良い
便利なアプリです🍀
今回はタスク管理機能をやります。
vuexを使用しています。
ログインユーザーで取得
gettersは全て
actionsでFirebaseから
getメソッドで取得し、
mutationsで上書きです。
書き込みは簡単そうだな〜と思い
読み取りからチャレンジしてみました。
ただルールをログインユーザーのみにし
書き込みに手をつけたら
mutations以外で上書きするな!
と後から例のエラーが出たので
また調整します🌱
順序的に絶対書き込みからやるべきだった。
##タスクの取得
送信しているデータはこんな感じで
ルールは誰でも読み書きできる状態。
###NGコード例①
まず始めに
v-showでアカウントuser.uidと
todosで送信しているuidと
一致するものだけを表示…
したかったのですが
これはNGでした❌
・そもそもv-forとv-ifの併用がNG💥
v-showは明記されていませんが
実際エラーだったのでNGのようです。
v-for-と一緒に-v-if-を使うのを避ける-必須
・他の人のデータも見れてしまうので
セキュリティ的にもNG
todosは配列にオブジェクトが入っています。
[{ task: '', uid: 'アカウント別のuid',}, {}, {}]
そのオブジェクト全ての中の
uidとする必要があります。
computedのtodosはpropsで
ListItemTaskに渡しているので
ここを直接いじることはできないな…
と思って関数を用意して
v-showを思いつきましたが、
上記の理由でNG。
普通にv-ifしてもeslintエラーなので
//eslint-disable-lineしましたが…
vue/no-use-v-if-with-v-for
やっぱりエラーが解消されず
公式見たらNGと。
<template>
<ul class="list list-task">
<li
is="ListItemTask"
v-show="user.uid === forTodo()"
v-for="todo in todos"
:key="todo.id"
:todos="todo"
></li>
</ul>
</template>
<script>
export default {
computed: {
user() {
return this.$store.getters.user
},
todos() {
return this.$store.getters['todo/todos'] //eslint-disable-line
},
},
methods: {
forTodo() {
const todos = this.$store.getters['todo/todos']
todos.forEach((value) => {
return value.uid
})
},
},
}
</script>
###成功コード例①
そしてこちらを参考にしました!
v-forとv-ifの併用はダメらしいんで対策した件
そもそもcomputedにfilterかければOK!
ということで書き換え。
propsのtype: Object変える必要あるかもと
気になっていましたが大丈夫でした🌟
ただ後述するコードの
.whereを使用した方が◎
filterもいらないし、
セキュリティ的にも安心だからです⭕️
<template>
<ul class="list list-task">
<li
is="ListItemTask"
v-for="todo in todos"
:key="todo.id"
:todos="todo"
></li>
</ul>
</template>
<script>
export default {
computed: {
user() {
return this.$store.getters.user
},
todos() {
return this.$store.getters['todo/todos'].filter((e) => {
return e.uid === this.user.uid
}) //eslint-disable-line
},
},
}
</script>
<style lang="scss" scoped>
.list-task {
}
</style>
###成功コード②
こちらがベストコード✨
export const actions = {
async getData({ commit }) {
try {
const user = this.$fire.auth.currentUser
const querySnapshot = await this.$fire.firestore
.collection('task')
.where('uid', '==', user.uid)
.get()
const todos = []
querySnapshot.forEach((doc) => {
const data = doc.data()
todos.push(data)
})
commit('setData', todos)
} catch (error) {
console.log(error)
}
},
}
ルールを変更してみる
上記のコードで成功したものの、
「そもそもfirebaseのルールを
書き換えた方が早いのでは?」
と思いチェック👀
ルールでユーザー情報を利用する
これはフィルターのような
データを絞る機能ではなく
実行するかしないかの
基準を設定みたいですね💡
ルールをコピペして変更し、
filterなしで全てのリストを表示に変更
<template>
<ul class="list list-task">
<li
is="ListItemTask"
v-for="todo in todos"
:key="todo.id"
:todos="todo"
></li>
</ul>
</template>
<script>
export default {
computed: {
user() {
return this.$store.getters.user
},
todos() {
return this.$store.getters['todo/todos']
},
},
}
</script>
ログインしてもエラー。
ルールがおかしいぞと思ってみたら
公式のコレクションの名前を
そのまま使用しているからですね。
ルールはログインしたアカウント情報
request.auth.uidと
自分の送信したデータにある
uidと一致すればOK
ということで変更
request.auth != null
!=で一致しないかどうか、
ゲストだったら空なので一致するためfalse
ログインしていたら空じゃないのでtrue
&&
かつ、という意味
taskコレクションの
自動生成されたIDにある
uidと一致すればOKなので変更
{ uid }はワイルドカードで
{ hoge }とか何でも良いものです。
taskコレクション内の
どのドキュメントにも適応されます。
基本的な読み書きのルール
rules_version = '2';
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 /task/{uid} {
allow read, write: if request.auth != null && request.auth.uid == resource.data.uid;
}
}
}
しかしこれでもエラー💥
こちらをチェックすると…
データを安全にクエリする
取得する際に
getメソッドを使用しているとNG❌
そして使っていました。
export const actions = {
async getData({ commit }) {
try {
const todos = []
const querySnapshot = await this.$fire.firestore.collection('task').get()
querySnapshot.forEach((doc) => {
const data = doc.data()
todos.push(data)
})
commit('setData', todos)
} catch (error) {
console.error("Error writing document: ", error) //eslint-disable-line
}
},
}
まずは取得のコードを修正
export const actions = {
async getData({ commit }) {
try {
const user = this.$fire.auth.currentUser
const querySnapshot = await this.$fire.firestore
.collection('task')
.where('uid', '==', user.uid)
.get()
const todos = []
querySnapshot.forEach((doc) => {
const data = doc.data()
todos.push(data)
})
commit('setData', querySnapshot)
} catch (error) {}
},
}
ところがこれでもエラー💣💥
forEachいらないのか❓
と思いきや…
いるみたいです。
クエリを実行する
書き込みはできても
例のエラーが出ます。
mutations以外でうんたらかんたら。
ということでこの続きをやっていきます。
まとめ
誰でも読み書きできるルールでも
テンプレートで
表示の切り替えはできました✨👏
ルール変更によるエラーは
解決していませんが、
セキュリティ面で
できるに越したことないので
続けてチャレンジしていきます!
🎈 WPでも公開中です
https://wp.me/pc9NHC-1m9
この記事が気に入ったらサポートをしてみませんか?