masalibの日記

システム開発、運用と猫の写真ブログです

Firebase入門 ユーザーの作成時にCloud Functionsを実行

FirebaseのユーザーはAuthenticationとい項目にはいります。このデータは他のユーザーからは参照できないです。FireStoreにも同じデータを入れて参照できるようにしたいと思います。 SingUPの処理にFireStoreにいれる処理を入ればいいのですが、他のプロバイダーの処理にも入れなくてはいけないのでそこは諦めてユーザーが作成された時に動かすFunctionを作って対応しました。

悲しい事にTwitter認証やGoogle認証はエミュレータでは動きません😢

この記事はReact Firebase入門シリーズです 1-1-1・ Firebase初期設定とFirebaseAuthのSignUp
1-1-2・ 「react-hook-form」を入れてみた
1-1-3・ AuthのSignUpの通信エラー対応
1-2 ・ FirebaseAuthのログイン処理
1-3 ・ FirebaseAuthのログイン認証とログアウト処理
1-4 ・ FirebaseAuthのパスワード初期化処理
1-5 ・ FirebaseAuthのメールアドレスの有効化
1-6 ・ FirebaseAuthのメールアドレスとパスワード変更
1-7 ・ FirebaseAuthの表示名変更
1-8 ・ FirebaseAuthの拡張項目追加
1-9-1 ・ FirebaseAuthのTwitter認証
1-9-2 ・ FirebaseAuthのTwitter認証(既存ユーザー向け)と解除
1-10 ・ FirebaseAuthのGoogle認証(既存ユーザー含む)と解除 2-1・ FirebaseStorageのファイルアップ:基礎
2-2・ FirebaseStorageのファイルアップ前に画像の切り抜き
2-3・ FirebaseStorageのファイルアップの移動
3-1・FirestoreのCRUD
3-2・Firestoreのデータ取得補足
3-3・Firestoreのページネーション処理
3-4・Firestoreのコレクション(テーブル)のJOIN
5・ FirebaseのHosting(デプロイ)
6-1・ Cloud FunctionsでHello,world
6-2・ Cloud Functions(エミュレータ)でHello,world
6-3・ ユーザーの作成時にCloud Functionsを実行 今ここ
よかったら他の記事も見てください。

やりたい事

  • ユーザー作成時にFireStoreにユーザー情報を格納する

プログラム

前回と同じで/funcions/index.jsを修正します。入っていないは思いますが firebase-adminが入っていないエラーが起きたらインストールしてください。
インストールする時はfunctionのフォルダに移動してからおこなってください

$ cd funcions
$ npm install firebase-admin

プログラムは至ってシンプル

const admin = require('firebase-admin');
admin.initializeApp();

exports.onCreateUser = functions.auth.user().onCreate(async(userRecord, _context) => {

    var email = userRecord.email ? userRecord.email : ""
    var photoURL = userRecord.photoURL ? userRecord.photoURL : ""
    var displayName = userRecord.displayName ? userRecord.displayName : ""

    var serverTimestamp = admin.firestore.FieldValue.serverTimestamp()

    functions.logger.info("user created", userRecord);
    await admin.firestore().collection('members').doc(userRecord.uid).set({
        docId: userRecord.uid,
        uid: userRecord.uid,
        email: email,
        displayName: displayName,
        photoURL: photoURL,
        departmentId: "9999",
        createdAt: serverTimestamp,
        updatedAt: serverTimestamp,
    });
    return;
});

解説

  • 「functions.auth.user().onCreate」がユーザー作成する時という意味になります。
  • 「async」をつけているのはDBの書き込みを一時的には待たないといけないからです。
 var email = userRecord.email ? userRecord.email : ""
 var photoURL = userRecord.photoURL ? userRecord.photoURL : ""
 var displayName = userRecord.displayName ? userRecord.displayName : ""

メールアドレス認証、Twitter認証,Google認証によってデータがあったりなかったりします。 ない場合にエラーにならないように分けています。

認証 email photoURL displayName
メールアドレス認証 入る 入らない 入らない
Twitter認証 入らない 入る 入る
Google認証 入る 入る 入る
  • タイムスタンプについて
    Cloud Functionsと通常のWEBで使う場合に微妙に違っていた

Cloud Functionsの場合

var serverTimestamp = admin.firestore.FieldValue.serverTimestamp()

WEBの場合

let timestamp = firebase.firestore.FieldValue.serverTimestamp()

結果

FireStoreの結果

Cloud Functionsのログ

i  functions: Beginning execution of "onCreateUser"
>  {"uid":"xOj7miKhkEvVNYKsx3Heqax3VzJX","email":"testttttttt@testtttt.com","emailVerified":false,"displayName":null,"photoURL":null,"phoneNumber":null,"disabled":false,"passwordHash":null,"passwordSalt":null,"tokensValidAfterTime":null,"metadata":{"creationTime":"1607767031120","lastSignInTime":"1607767031120"},"customClaims":{},"providerData":[{"providerId":"password","email":"testttttttt@testtttt.com","federatedId":"testttttttt@testtttt.com","rawId":"testttttttt@testtttt.com"}]}
i  functions: Finished "onCreateUser" in ~1s

できていない事

  • エラー(タイムアウトなど)が起きた時にログ出力するや通知したりする機能。
  • FireStoreに書き込みをおこなっていますが、他のサーバーを叩いて書き込みをする
  • ユーザーの作成時にメールアドレスの有効化のメール送信
  • functionsが1つのファイルになっているが今後の事を考えると機能によってわけたい

感想

ユーザー作成時にFireStoreに書き込みができました。ずーとやりたかった。 できていない事が多々あるのでそちらも改善していきたい。