Skip to content

Commit

Permalink
Merge pull request #174 from MurakawaTakuya/fix/173-get-app-check-tok…
Browse files Browse the repository at this point in the history
…en-on-request

App CheckのtokenをAPI使用時に取得するように変更
  • Loading branch information
MurakawaTakuya authored Jan 28, 2025
2 parents e618d2a + 42dd370 commit fbead8d
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 58 deletions.
15 changes: 15 additions & 0 deletions src/Components/DashBoard/DashBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ export default function DashBoard({
limit,
})
.then((data) => {
if (
!data ||
!data.successResults ||
!data.failedResults ||
!data.pendingResults
) {
showSnackBar({
message: "データの取得に失敗しました。ログインし直してください。",
type: "warning",
});
return;
}
// 既に追加されている場合は追加しない
setSuccessResults((prev) => {
const newResults = data.successResults.filter(
Expand Down Expand Up @@ -213,6 +225,9 @@ export default function DashBoard({
limit: 1,
})
.then((data) => {
if (!data.successResults) {
return;
}
if (data.successResults.length > 0) {
setLastPostDate(data.successResults[0].post?.submittedAt);
}
Expand Down
20 changes: 19 additions & 1 deletion src/Components/GoalModal/DeleteGoalModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import getAppCheckToken from "@/utils/getAppCheckToken";
import { useDeleteGoal } from "@/utils/ResultContext";
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
import { DialogContent, DialogTitle, Modal, ModalDialog } from "@mui/joy";
Expand All @@ -14,6 +15,23 @@ export default function DeleteGoalModal({ goalId }: { goalId: string }) {
const [open, setOpen] = useState(false);

const handleDelete = async () => {
const appCheckToken = await getAppCheckToken().catch((error) => {
showSnackBar({
message: error.message,
type: "warning",
});
return "";
});

if (!appCheckToken) {
showSnackBar({
message:
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。",
type: "warning",
});
return;
}

try {
const response = await fetch(`${functionsEndpoint}/goal/${goalId}`, {
method: "DELETE",
Expand Down
20 changes: 19 additions & 1 deletion src/Components/NameUpdate/NameUpdate.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";
import { appCheckToken, auth, functionsEndpoint } from "@/app/firebase";
import { auth, functionsEndpoint } from "@/app/firebase";
import getAppCheckToken from "@/utils/getAppCheckToken";
import { useUser } from "@/utils/UserContext";
import {
DialogContent,
Expand Down Expand Up @@ -33,6 +34,23 @@ export default function NameUpdate() {
return;
}

const appCheckToken = await getAppCheckToken().catch((error) => {
showSnackBar({
message: error.message,
type: "warning",
});
return "";
});

if (!appCheckToken) {
showSnackBar({
message:
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。",
type: "warning",
});
return;
}

try {
const response = await fetch(
`${functionsEndpoint}/user/${user?.userId}`,
Expand Down
20 changes: 19 additions & 1 deletion src/Components/PostModal/DeletePostModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import getAppCheckToken from "@/utils/getAppCheckToken";
import { useDeletePost } from "@/utils/ResultContext";
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
import { DialogContent, DialogTitle, Modal, ModalDialog } from "@mui/joy";
Expand All @@ -20,6 +21,23 @@ export default function DeletePostModal({
const [open, setOpen] = useState(false);

const handleDelete = async () => {
const appCheckToken = await getAppCheckToken().catch((error) => {
showSnackBar({
message: error.message,
type: "warning",
});
return "";
});

if (!appCheckToken) {
showSnackBar({
message:
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。",
type: "warning",
});
return;
}

try {
const response = await fetch(`${functionsEndpoint}/post/${goalId}`, {
method: "DELETE",
Expand Down
6 changes: 3 additions & 3 deletions src/Components/Progress/Progress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default function Progress({
return (
<SuccessStep
key={result.goalId}
result={result as GoalWithIdAndUserData}
result={result}
user={user as User}
isBlured={
result.post?.submittedAt && lastPostDate
Expand All @@ -64,15 +64,15 @@ export default function Progress({
return (
<FailedStep
key={result.goalId}
result={result as GoalWithIdAndUserData}
result={result}
user={user as User}
/>
);
} else if (result.type === "pending") {
return (
<PendingStep
key={result.goalId}
result={result as GoalWithIdAndUserData}
result={result}
user={user as User}
/>
);
Expand Down
41 changes: 1 addition & 40 deletions src/app/firebase.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { showSnackBar } from "@/Components/SnackBar/SnackBar";
import { Analytics, getAnalytics } from "firebase/analytics";
import { initializeApp } from "firebase/app";
import {
getToken,
initializeAppCheck,
ReCaptchaV3Provider,
} from "firebase/app-check";
import {
browserLocalPersistence,
connectAuthEmulator,
Expand All @@ -31,44 +25,11 @@ export const storage = getStorage(app);
export const auth = getAuth(app);
let messaging: Messaging | null = null;
let analytics: Analytics | null = null;
let appCheckToken = "";

// クライアントサイドでのみ実行する初期化
if (typeof window !== "undefined") {
messaging = getMessaging(app);
analytics = getAnalytics(app);

// 開発環境ならApp Checkを使用しない
// ステージング環境でApp Checkのデバッグトークンを有効にする
if (process.env.NODE_ENV !== "development") {
if (process.env.NEXT_PUBLIC_IS_STAGING === "true") {
(
window as unknown as { FIREBASE_APPCHECK_DEBUG_TOKEN: boolean }
).FIREBASE_APPCHECK_DEBUG_TOKEN = true;
console.log("App Check Debug Token Enabled");
}
// App Checkの設定
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaV3Provider(
process.env.NEXT_PUBLIC_FIREBASE_RECAPTCHA_SITEKEY as string
),
isTokenAutoRefreshEnabled: true,
});

getToken(appCheck)
.then((token) => {
console.log("App Check: Success");
appCheckToken = token.token;
})
.catch((error) => {
console.log(error.message);
showSnackBar({
message:
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。",
type: "warning",
});
});
}
}

export const googleProvider = new GoogleAuthProvider();
Expand Down Expand Up @@ -99,5 +60,5 @@ if (process.env.NODE_ENV === "production") {
console.log("Functions: Emulator");
}

export { analytics, appCheckToken, functionsEndpoint, messaging };
export { analytics, functionsEndpoint, messaging };
console.log("firebaseConfig initialized");
9 changes: 8 additions & 1 deletion src/utils/API/Goal/createGoal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import { Goal } from "@/types/types";
import getAppCheckToken from "@/utils/getAppCheckToken";

/**
* Cloud FunctionsのAPIを呼び出して、目標をFirestoreに登録する
Expand All @@ -18,6 +19,8 @@ export const createGoal = async (postData: Goal) => {
throw new Error("too long comment");
}

const appCheckToken = await getAppCheckToken();

const response = await fetch(`${functionsEndpoint}/goal/`, {
method: "POST",
headers: {
Expand Down Expand Up @@ -61,6 +64,10 @@ export const handleCreateGoalError = (error: unknown) => {
if (error.message.includes("500")) {
snackBarMessage = "サーバーエラーが発生しました";
}
if (error.message.includes("App Checkの初期化に失敗しました。")) {
snackBarMessage =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。";
}
} else {
console.error("An unknown error occurred");
snackBarMessage = "不明なエラーが発生しました";
Expand Down
9 changes: 8 additions & 1 deletion src/utils/API/Goal/updateGoal.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import getAppCheckToken from "@/utils/getAppCheckToken";

/**
* Cloud FunctionsのAPIを呼び出して、目標を編集する
Expand Down Expand Up @@ -27,6 +28,8 @@ export const updateGoal = async (
throw new Error("too long comment");
}

const appCheckToken = await getAppCheckToken();

const response = await fetch(`${functionsEndpoint}/goal/${goalId}`, {
method: "PUT",
headers: {
Expand Down Expand Up @@ -70,6 +73,10 @@ export const handleUpdateGoalError = (error: unknown) => {
if (error.message.includes("500")) {
snackBarMessage = "サーバーエラーが発生しました";
}
if (error.message.includes("App Checkの初期化に失敗しました。")) {
snackBarMessage =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。";
}
} else {
console.error("An unknown error occurred");
snackBarMessage = "不明なエラーが発生しました";
Expand Down
9 changes: 8 additions & 1 deletion src/utils/API/Post/createPost.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import { PostWithGoalId } from "@/types/types";
import getAppCheckToken from "@/utils/getAppCheckToken";

/**
* Cloud FunctionsのAPIを呼び出して、投稿をFirestoreに登録する
Expand All @@ -13,6 +14,8 @@ export const createPost = async (postData: PostWithGoalId) => {
throw new Error("too long comment");
}

const appCheckToken = await getAppCheckToken();

const response = await fetch(`${functionsEndpoint}/post/`, {
method: "POST",
headers: {
Expand Down Expand Up @@ -53,6 +56,10 @@ export const handleCreatePostError = (error: unknown) => {
if (error.message.includes("500")) {
snackBarMessage = "サーバーエラーが発生しました";
}
if (error.message.includes("App Checkの初期化に失敗しました。")) {
snackBarMessage =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。";
}
} else {
console.error("An unknown error occurred");
snackBarMessage = "不明なエラーが発生しました";
Expand Down
5 changes: 4 additions & 1 deletion src/utils/API/Reaction/updateReaction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import { ReactionTypeMap } from "@/types/types";
import getAppCheckToken from "@/utils/getAppCheckToken";

/**
* Cloud FunctionsのAPIを呼び出して、リアクションを更新する
Expand All @@ -15,6 +16,8 @@ export const updateReaction = async (
goalId: string,
reactionType: ReactionTypeMap | ""
) => {
const appCheckToken = await getAppCheckToken();

const response = await fetch(`${functionsEndpoint}/reaction/${goalId}`, {
method: "PUT",
headers: {
Expand Down
9 changes: 8 additions & 1 deletion src/utils/API/Result/fetchResult.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import getAppCheckToken from "@/utils/getAppCheckToken";

/**
* Cloud FunctionsのAPIを呼び出して、結果の一覧を取得する
Expand Down Expand Up @@ -34,6 +35,8 @@ export const fetchResult = async ({
queryParams.append("limit", limit.toString());
}

const appCheckToken = await getAppCheckToken();

const response = await fetch(
`${functionsEndpoint}/result/${userId}?${queryParams.toString()}`,
{
Expand Down Expand Up @@ -75,6 +78,10 @@ export const handleFetchResultError = (error: unknown) => {
if (error.message.includes("500")) {
snackBarMessage = "サーバーエラーが発生しました";
}
if (error.message.includes("App Checkの初期化に失敗しました。")) {
snackBarMessage =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。";
}
} else {
console.error("An unknown error occurred");
snackBarMessage = "不明なエラーが発生しました";
Expand Down
9 changes: 8 additions & 1 deletion src/utils/API/User/fetchUser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { appCheckToken, functionsEndpoint } from "@/app/firebase";
import { functionsEndpoint } from "@/app/firebase";
import { User } from "@/types/types";
import getAppCheckToken from "@/utils/getAppCheckToken";

/**
* Cloud FunctionsのAPIを呼び出して、ユーザー情報をFirestoreから取得する
Expand All @@ -8,6 +9,8 @@ import { User } from "@/types/types";
* @return {*} {Promise<User>}
*/
export const fetchUserById = async (userId: string): Promise<User> => {
const appCheckToken = await getAppCheckToken();

const response = await fetch(`${functionsEndpoint}/user/id/${userId}`, {
method: "GET",
headers: {
Expand Down Expand Up @@ -45,6 +48,10 @@ export const handleFetchUserError = (error: unknown) => {
if (error.message.includes("429")) {
snackBarMessage = "リクエストが多すぎます。数分後に再度お試しください。";
}
if (error.message.includes("App Checkの初期化に失敗しました。")) {
snackBarMessage =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。";
}
} else {
console.error("An unknown error occurred");
snackBarMessage = "不明なエラーが発生しました";
Expand Down
5 changes: 5 additions & 0 deletions src/utils/Auth/signInWithGoogleAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export const signInWithGoogleAccount = async () => {
"Googleアカウントでのログインに失敗しました。ページを更新して再度お試しください。";
if ((error as Error)?.message.includes("auth/popup-closed-by-user")) {
message = "ログインがキャンセルされました";
} else if (
(error as Error)?.message.includes("appCheck/fetch-status-error")
) {
message =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください。";
}
showSnackBar({
message,
Expand Down
3 changes: 3 additions & 0 deletions src/utils/Auth/signInWithMail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export const signInWithMail = async (email: string, password: string) => {
} else if (errorMessage.includes("auth/too-many-requests")) {
snackBarMessage =
"リクエストが多すぎます。しばらくしてからもう一度お試しください。";
} else if (errorMessage.includes("appCheck/fetch-status-error")) {
snackBarMessage =
"App Checkの初期化に失敗しました。debug tokenがサーバーに登録されていることを確認してください";
}

showSnackBar({
Expand Down
Loading

0 comments on commit fbead8d

Please sign in to comment.