diff --git a/functions/src/index.ts b/functions/src/index.ts index c84668e..244aa83 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -3,7 +3,8 @@ import express from "express"; import { rateLimit } from "express-rate-limit"; import admin from "firebase-admin"; import { logger } from "firebase-functions"; -import { onRequest } from "firebase-functions/v2/https"; +import { HttpsError, onRequest } from "firebase-functions/v2/https"; +import { beforeUserCreated } from "firebase-functions/v2/identity"; import helmet from "helmet"; import serviceAccount from "./serviceAccountKey.json"; @@ -138,3 +139,32 @@ export const helloWorld = onRequest({ region: region }, (req, res) => { logger.info("Hello log!", { structuredData: true }); res.send("Hello World!"); }); + +const db = admin.firestore(); + +// アカウント作成時に実行される処理 +export const beforecreated = beforeUserCreated( + { region: region }, + async (event) => { + const user = event.data; + + if (!user) { + throw new HttpsError("invalid-argument", "No user data provided."); + } + const userId = user?.uid; + const name = user?.displayName || "No Name"; + + try { + await db.collection("user").doc(userId).set({ + name: name, + streak: 0, + fcmToken: "", + }); + } catch (error) { + logger.error(error); + throw new HttpsError("internal", "Error creating user data."); + } + + return; + } +); diff --git a/src/app/firebase.ts b/src/app/firebase.ts index b5b0853..c9df1ab 100644 --- a/src/app/firebase.ts +++ b/src/app/firebase.ts @@ -55,7 +55,7 @@ if (typeof window !== "undefined") { isTokenAutoRefreshEnabled: true, }); - getToken(appCheck) + await getToken(appCheck) .then((token) => { console.log("App Check: Success"); appCheckToken = token.token; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f29f3ea..8443975 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -39,6 +39,7 @@ export default function RootLayout({ + {/* Open Graph */} diff --git a/src/utils/API/User/createUser.ts b/src/utils/API/User/createUser.ts deleted file mode 100644 index 0f57cc5..0000000 --- a/src/utils/API/User/createUser.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { appCheckToken, functionsEndpoint } from "@/app/firebase"; - -/** - * Cloud FunctionsのAPIを呼び出して、ユーザー情報をFirestoreに登録する - * AuthenticationのuserIdと/userのdocument IDは同じにする - * - * @param {string} name - * @param {string} userId - */ -export const createUser = async (name: string, userId: string) => { - const response = await fetch(`${functionsEndpoint}/user/`, { - method: "POST", - headers: { - "X-Firebase-AppCheck": appCheckToken, - "Content-Type": "application/json", - }, - body: JSON.stringify({ userId, name }), - }); - - if (!response.ok) { - const status = response.status; - const data = await response.json(); - throw new Error(`Error ${status}: ${data.message}`); - } -}; diff --git a/src/utils/API/User/fetchUser.ts b/src/utils/API/User/fetchUser.ts index 577f38a..5b5cfc6 100644 --- a/src/utils/API/User/fetchUser.ts +++ b/src/utils/API/User/fetchUser.ts @@ -33,7 +33,7 @@ export const fetchUserById = async (userId: string): Promise => { * @return {*} */ export const handleFetchUserError = (error: unknown) => { - let snackBarMessage = "初回ログインかユーザーデータが見つかりません"; + let snackBarMessage = "ユーザーデータが見つかりません"; if (error instanceof Error) { if (error.message.includes("404")) { diff --git a/src/utils/Auth/signInWithGoogleAccount.ts b/src/utils/Auth/signInWithGoogleAccount.ts index 0c508b7..8781fe7 100644 --- a/src/utils/Auth/signInWithGoogleAccount.ts +++ b/src/utils/Auth/signInWithGoogleAccount.ts @@ -1,29 +1,15 @@ import { auth, googleProvider } from "@/app/firebase"; import { showSnackBar } from "@/Components/SnackBar/SnackBar"; -import { createUser } from "@/utils/API/User/createUser"; -import { updateUser } from "@/utils/UserContext"; -import { getAdditionalUserInfo, signInWithPopup } from "firebase/auth"; +import { signInWithPopup } from "firebase/auth"; /** * Firebase Authenticationを使ってGoogleアカウントでログインする - * 初回ログインの時のみデータベースにユーザー情報を登録する + * * */ export const signInWithGoogleAccount = async () => { try { - const result = await signInWithPopup(auth, googleProvider); - - // 初めての時だけユーザー情報を登録する - if (getAdditionalUserInfo(result)?.isNewUser) { - // uidとdocument IDを一致させる - await createUser(result.user.displayName ?? "no name", result.user.uid); - updateUser({ - userId: result.user.uid, - name: result.user.displayName ?? "no name", - loginType: "Google", - isMailVerified: result.user.emailVerified, - }); - } + await signInWithPopup(auth, googleProvider); showSnackBar({ message: "Googleアカウントでログインしました", diff --git a/src/utils/Auth/signUpWithMail.tsx b/src/utils/Auth/signUpWithMail.tsx index 1f30fdb..e739f6e 100644 --- a/src/utils/Auth/signUpWithMail.tsx +++ b/src/utils/Auth/signUpWithMail.tsx @@ -1,12 +1,11 @@ -import { auth } from "@/app/firebase"; +import { appCheckToken, auth, functionsEndpoint } from "@/app/firebase"; import { showSnackBar } from "@/Components/SnackBar/SnackBar"; -import { createUser } from "@/utils/API/User/createUser"; -import { updateUser } from "@/utils/UserContext"; import { createUserWithEmailAndPassword, sendEmailVerification, updateProfile, } from "firebase/auth"; +import { updateUser } from "../UserContext"; /** * Firebase Authenticationを使ってメールでユーザーを作成し、生成されたuserIdをドキュメントIDとしてFirestoreにユーザー情報を登録する @@ -33,8 +32,22 @@ export const signUpWithMail = async ( console.error("プロファイル更新に失敗しました:", profileUpdateError); } - // userIdとdocument IDを一致させる - await createUser(name, user.uid); + // displayNameをFirestoreに登録 + const response = await fetch(`${functionsEndpoint}/user/${user.uid}`, { + method: "PUT", + headers: { + "X-Firebase-AppCheck": appCheckToken, + "Content-Type": "application/json", + }, + body: JSON.stringify({ name }), + }); + + if (!response.ok) { + const status = response.status; + const data = await response.json(); + throw new Error(`Error ${status}: ${data.message}`); + } + updateUser({ userId: user.uid, name: name, @@ -46,7 +59,7 @@ export const signUpWithMail = async ( try { await sendEmailVerification(user); } catch (verificationError) { - console.error("failed to send email verification:", verificationError); + console.error("Failed to send email verification:", verificationError); } showSnackBar({ diff --git a/src/utils/UserContext.tsx b/src/utils/UserContext.tsx index efd01b2..3d92941 100644 --- a/src/utils/UserContext.tsx +++ b/src/utils/UserContext.tsx @@ -85,8 +85,6 @@ export const UserProvider = ({ children }: Props) => { try { const userData = await fetchUserById(firebaseUser.uid); - // ユーザーデータを作成する前にfetchしようとして"User not found"になるので、postした場所でsetさせている - // "User not found"ではない(= 初回ログイン直後ではない)場合のみsetする if (userData.userId) { setUser({ ...userData,