web-dev-qa-db-ja.com

Cloud Functions for FirebaseのFirestoreトリガーからユーザーIDを取得しますか?

以下の例では、「offers/{offerId}」に書き込んだユーザーのユーザーID(uid)を取得する方法はありますか? ここ のようにしてみましたが、Firestoreでは機能しません。

exports.onNewOffer = functions.firestore
  .document('offers/{offerId}')
  .onCreate(event => {
    ...
});
11
Gabriel Bessa

私はしばらくこれに苦労していて、ようやくFirebaseサポートに連絡しました:

I was trying to achieve this.

_event.auth.uid_は、firestoreデータベーストリガーのイベントオブジェクトでは定義されていません。 (リアルタイムデータベーストリガーで機能します)

console.log(event)を実行すると、出力にauthが見つかりません。

公式サポートの回答:

申し訳ありませんが、authはまだFirestore SDKに追加されていません。次の機能にリストされています。

今後のアップデートについては、リリースノートをご覧ください。

これで誰かが数時間節約できるといいのですが。

18
Tim

私がこれを解決した方法の要約/実行可能なソリューション:

クライアント上

ログイン/現在のユーザーのuid(例:creatorId)を、作成中のエンティティに追加します。このuidにアクセスするには、firebase.auth().onAuthStateChanged()ユーザーオブジェクトをアプリの状態で保存します。

Firebase Firestore /データベース内

セキュリティルールをcreateに追加して、クライアント提供のcreatorId値が認証済みユーザーのuidと同じであることを検証します。これで、クライアントがcreatorIdを偽装しておらず、この値を他の場所で信頼できることがわかりました。

例えば.

match /entity/{entityId} {
  allow create: if madeBySelf();
}

function madeBySelf() {
  return request.auth.uid == request.resource.data.creatorId;
}

Firebase関数内

作成されたエンティティタイプにonCreateトリガーを追加して、クライアントが提供し、検証されたcreatorIdを使用して、作成中のユーザーのプロファイル情報を検索し、この情報を新しいエンティティに関連付け/追加しますドク。

これは次の方法で実現できます。

  1. 新しいアカウントが作成されたときにusersコレクションと個々のuserドキュメントを作成し、新しいuser文書にアプリで使用できるフィールド(displayNameなど)を入力します。これは、Firebase Authenticationシステムによって公開されたフィールドがコンシューマーアプリで使用するには不十分であるため(たとえば、displayNameおよびavatarURLが公開されていない)、作成したものを調べるだけでは信頼できないためです。その方法でユーザーの情報。

    例えば(ES6を使用)

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'

const APP = admin.initializeApp()

export const createUserRecord = functions.auth.user()
  .onCreate(async (userRecord, context) => {
    const userDoc = {
      id: userRecord.uid,
      displayName: userRecord.displayName || "No Name",
      avatarURL: userRecord.photoURL || '',
    }
    return APP.firestore().collection('users').doc(userRecord.uid).set(userDoc)
  })
  1. 検証済みのcreatorId値と便利なuserオブジェクトを取得したので、エンティティタイプ(または作成したすべてのエンティティ)にonCreateトリガーを追加して、作成中のユーザーのinfoを作成したオブジェクトに追加します。
export const addCreatorToDatabaseEntry = functions.firestore
  .document('<your entity type here>/{entityId}')
  .onCreate(async (snapshot, context) => {
    const userDoc = await APP.firestore().collection('users').doc(snapshot.data().creatorId).get()
    return snapshot.ref.set({ creator: userDoc.data() }, { merge: true })
})

これは明らかにシステム全体で多くの重複したユーザー情報データにつながります-そして、あなたができる少しのクリーンアップがあります( 'creatorId`は上記の実装で作成されたエンティティで重複しています)-しかし今やそれは非常に簡単に表示できますアプリ全体で何を作成し、「Firebaseの方法」のように見える人。

お役に立てれば。私はFirebaseがいくつかの点で非常に優れていることを発見し、いくつかの通常は簡単なこと(このように)を「すべき」よりも難しくしました。バランスの取れた大ファンですが。

3
Ethan

これがfirestore関数に追加されるまでの回避策は、ドキュメントの作成時にuser_idをフィールドとして追加し、その後削除することです。次に、関数onCreateでそれを取得し、それを必要な目的に使用した後、関数内でそのドキュメントからフィールドを削除します。

2
askilondz

すでに上記で提案されているように、回避策は、データ自体を含むuser_idフィールドを追加し、サーバーでそれを読み取ることです。

このアプローチの欠点は、セキュリティの抜け穴になることです。サーバーでユーザーIDを確認していないため、他のユーザーは、IDをデータと共に送信することにより、他のユーザーになりすますことができます。

セキュリティが重要なアプリケーションの場合、解決策は、セキュリティルールを使用して、正しいuser_idがデータとともに送信されたことを確認することです。

allow write: if resource.data.user_id == request.auth.uid;
2
Akshay Jain

これでうまくいくはずです:

exports.newMessage = functions.firestore
        .document('groups/messages/{messageId}')
        .onCreate((snap, context) => {
            var fromId = snap.data().fromId;
0
Doron Goldberg

snap._fieldsProto.uid.stringValueについて

例:

exports.hello = functions.firestore.document('hello/{worldId}').onCreate((snap, context) => {
   console.log(snap._fieldsProto.uid.stringValue)
});
0
l2aelba