From fb88307cdd8e4ec05308290e716dfb55f32b40bd Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Wed, 24 Jul 2024 15:19:26 +0700 Subject: [PATCH 01/17] setup local emulator but still error --- functions/.gitignore | 4 +++- functions/package.json | 2 +- hosting/.gitignore | 2 ++ hosting/src/hooks/useFirebaseUi.tsx | 14 ++++++++++---- hosting/src/plugins/firebase.ts | 13 ++++++++++--- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/functions/.gitignore b/functions/.gitignore index 9be0f014..8032bda4 100644 --- a/functions/.gitignore +++ b/functions/.gitignore @@ -1,4 +1,5 @@ # Compiled JavaScript files +lib lib/**/*.js lib/**/*.js.map @@ -7,4 +8,5 @@ typings/ # Node.js dependency directory node_modules/ -*.local \ No newline at end of file +*.local +yarn.lock \ No newline at end of file diff --git a/functions/package.json b/functions/package.json index d2fe9802..4a68c777 100644 --- a/functions/package.json +++ b/functions/package.json @@ -12,7 +12,7 @@ "lint:fix": "npm run lint --fix", "logs": "firebase functions:log", "prettier:fix": "prettier --write .", - "serve": "npm run build && firebase emulators:start --only functions", + "serve": "npm run build && firebase emulators:start --only auth,functions,firestore", "shell": "npm run build && firebase functions:shell" }, "name": "functions", diff --git a/hosting/.gitignore b/hosting/.gitignore index fd3dbb57..bdbca36d 100644 --- a/hosting/.gitignore +++ b/hosting/.gitignore @@ -34,3 +34,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +yarn.lock diff --git a/hosting/src/hooks/useFirebaseUi.tsx b/hosting/src/hooks/useFirebaseUi.tsx index 06446557..2daed6fe 100644 --- a/hosting/src/hooks/useFirebaseUi.tsx +++ b/hosting/src/hooks/useFirebaseUi.tsx @@ -1,9 +1,9 @@ "use client"; -import {firebaseAuth} from "@/plugins/firebase"; -import {auth as firebaseAuthUi} from "firebaseui"; -import {AuthCredential, GoogleAuthProvider} from "firebase/auth"; +import { firebaseAuth } from "@/plugins/firebase"; +import { AuthCredential, EmailAuthProvider, GoogleAuthProvider } from "firebase/auth"; +import { auth as firebaseAuthUi } from "firebaseui"; import "firebaseui/dist/firebaseui.css"; -import {useEffect, useState} from "react"; +import { useEffect, useState } from "react"; const firebaseUi = firebaseAuthUi.AuthUI.getInstance() || new firebaseAuthUi.AuthUI(firebaseAuth); @@ -31,6 +31,12 @@ export function useFirebaseUi() { tosUrl: "https://github.com/oddbit/tanam/blob/main/docs/tos.md", privacyPolicyUrl: "https://github.com/oddbit/tanam/blob/main/docs/privacy-policy.md", signInOptions: [ + { + provider: EmailAuthProvider.PROVIDER_ID, + fullLabel: isSignUp + ? "Sign up with email" + : "Sign in with email" + }, { provider: GoogleAuthProvider.PROVIDER_ID, fullLabel: isSignUp ? "Sign up with Google" : "Sign in with Google", diff --git a/hosting/src/plugins/firebase.ts b/hosting/src/plugins/firebase.ts index 33d95b3d..b0df01fd 100644 --- a/hosting/src/plugins/firebase.ts +++ b/hosting/src/plugins/firebase.ts @@ -1,6 +1,6 @@ -import {initializeApp} from "firebase/app"; -import {getAuth} from "firebase/auth"; -import {getFirestore} from "firebase/firestore"; +import { initializeApp } from "firebase/app"; +import { connectAuthEmulator, getAuth } from "firebase/auth"; +import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, @@ -15,3 +15,10 @@ const firebaseConfig = { export const firebaseApp = initializeApp(firebaseConfig); export const firebaseAuth = getAuth(firebaseApp); export const firestore = getFirestore(firebaseApp); + +console.info('process.env.NEXT_ENV :: ', process.env.NEXT_ENV) + +// Connect to the emulator +if (process.env.NEXT_ENV === "local") { + connectAuthEmulator(firebaseAuth, process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ?? "http://localhost:9099") +} From 25480f7db8c67b15255563d633956f22ccaa531c Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 14:52:17 +0700 Subject: [PATCH 02/17] remove unsed --- hosting/src/components/Header/index.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index 750a625d..2302772b 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -1,18 +1,13 @@ import DarkModeSwitcher from "@/components/Header/DarkModeSwitcher"; import DropdownUser from "@/components/Header/DropdownUser"; -import {useAuthentication} from "@/hooks/useAuthentication"; +import { useAuthentication } from "@/hooks/useAuthentication"; import Image from "next/image"; import Link from "next/link"; -import {useEffect} from "react"; -import {useTanamUser} from "../../hooks/useTanamUser"; +import { useTanamUser } from "../../hooks/useTanamUser"; const Header = (props: {sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void}) => { const {authUser} = useAuthentication(); - const {data: tanamUser, error: userError} = useTanamUser(authUser?.uid); - - useEffect(() => { - console.log("userError", userError); - }, [userError]); + const {data: tanamUser} = useTanamUser(authUser?.uid); return (
From 3bfceaf67c99d34f09240b4e556a9d2383db8977 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 16:36:10 +0700 Subject: [PATCH 03/17] create error page --- hosting/src/app/(protected)/error/page.tsx | 27 ++++++++++++++++++++++ hosting/src/components/Header/index.tsx | 7 +++++- hosting/src/hooks/useTanamUser.tsx | 17 ++++++++++---- 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 hosting/src/app/(protected)/error/page.tsx diff --git a/hosting/src/app/(protected)/error/page.tsx b/hosting/src/app/(protected)/error/page.tsx new file mode 100644 index 00000000..76cffdcb --- /dev/null +++ b/hosting/src/app/(protected)/error/page.tsx @@ -0,0 +1,27 @@ +"use client"; +import Notification from "@/components/common/Notification"; +import PageHeader from "@/components/common/PageHeader"; +import { useAuthentication } from "@/hooks/useAuthentication"; +import { useTanamUser } from "@/hooks/useTanamUser"; +import { useEffect } from "react"; + +export default function ErrorPage() { + const {authUser} = useAuthentication(); + const {data: tanamUser, error: userError} = useTanamUser(authUser?.uid); + + useEffect(() => { + console.log("userError", userError?.message); + }, [userError]); + + return ( + <> + authUser :: {JSON.stringify(authUser)} + + + + ); +} diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index 2302772b..e3ae10d2 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -3,11 +3,16 @@ import DropdownUser from "@/components/Header/DropdownUser"; import { useAuthentication } from "@/hooks/useAuthentication"; import Image from "next/image"; import Link from "next/link"; +import { useEffect } from "react"; import { useTanamUser } from "../../hooks/useTanamUser"; const Header = (props: {sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void}) => { const {authUser} = useAuthentication(); - const {data: tanamUser} = useTanamUser(authUser?.uid); + const {data: tanamUser, error: userError} = useTanamUser(authUser?.uid); + + useEffect(() => { + console.log("userError", userError); + }, [userError]); return (
diff --git a/hosting/src/hooks/useTanamUser.tsx b/hosting/src/hooks/useTanamUser.tsx index 4ac40bd1..c0beb43f 100644 --- a/hosting/src/hooks/useTanamUser.tsx +++ b/hosting/src/hooks/useTanamUser.tsx @@ -1,8 +1,8 @@ -import {TanamUserClient} from "@/models/TanamUserClient"; -import {UserNotification} from "@/models/UserNotification"; -import {firestore} from "@/plugins/firebase"; -import {doc, onSnapshot} from "firebase/firestore"; -import {useEffect, useState} from "react"; +import { TanamUserClient } from "@/models/TanamUserClient"; +import { UserNotification } from "@/models/UserNotification"; +import { firestore } from "@/plugins/firebase"; +import { doc, onSnapshot } from "firebase/firestore"; +import { useEffect, useState } from "react"; interface UseTanamDocumentsResult { data: TanamUserClient | null; @@ -29,7 +29,14 @@ export function useTanamUser(uid?: string): UseTanamDocumentsResult { const unsubscribe = onSnapshot( docRef, (snapshot) => { + console.info("tanamUser snapshot :: ", snapshot.exists) + + if (!snapshot.exists()) { + setError(new UserNotification("error", "Error user doesnt exist", "We can't found the user")); + } + const tanamUser = TanamUserClient.fromFirestore(snapshot); + console.info("tanamUser :: ", tanamUser) setData(tanamUser); }, (err) => { From 07144dea50b121b0b7e73537a5f1f9f6cd6188a1 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 16:42:10 +0700 Subject: [PATCH 04/17] create error page --- hosting/src/app/(protected)/error/page.tsx | 14 ++++---------- hosting/src/hooks/useTanamUser.tsx | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/hosting/src/app/(protected)/error/page.tsx b/hosting/src/app/(protected)/error/page.tsx index 76cffdcb..15973ec3 100644 --- a/hosting/src/app/(protected)/error/page.tsx +++ b/hosting/src/app/(protected)/error/page.tsx @@ -3,24 +3,18 @@ import Notification from "@/components/common/Notification"; import PageHeader from "@/components/common/PageHeader"; import { useAuthentication } from "@/hooks/useAuthentication"; import { useTanamUser } from "@/hooks/useTanamUser"; -import { useEffect } from "react"; export default function ErrorPage() { const {authUser} = useAuthentication(); - const {data: tanamUser, error: userError} = useTanamUser(authUser?.uid); - - useEffect(() => { - console.log("userError", userError?.message); - }, [userError]); + const {error: userError} = useTanamUser(authUser?.uid); return ( <> - authUser :: {JSON.stringify(authUser)} - + ); diff --git a/hosting/src/hooks/useTanamUser.tsx b/hosting/src/hooks/useTanamUser.tsx index c0beb43f..3fde0888 100644 --- a/hosting/src/hooks/useTanamUser.tsx +++ b/hosting/src/hooks/useTanamUser.tsx @@ -32,7 +32,7 @@ export function useTanamUser(uid?: string): UseTanamDocumentsResult { console.info("tanamUser snapshot :: ", snapshot.exists) if (!snapshot.exists()) { - setError(new UserNotification("error", "Error user doesnt exist", "We can't found the user")); + setError(new UserNotification("error", "Access Denied", "Sorry you cant access the page")); } const tanamUser = TanamUserClient.fromFirestore(snapshot); From 4a3d548cf8c3a3ce359e067efabb9cbec46e267a Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 16:42:29 +0700 Subject: [PATCH 05/17] remove unused --- hosting/src/hooks/useTanamUser.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/hosting/src/hooks/useTanamUser.tsx b/hosting/src/hooks/useTanamUser.tsx index 3fde0888..d7c6f81b 100644 --- a/hosting/src/hooks/useTanamUser.tsx +++ b/hosting/src/hooks/useTanamUser.tsx @@ -29,14 +29,11 @@ export function useTanamUser(uid?: string): UseTanamDocumentsResult { const unsubscribe = onSnapshot( docRef, (snapshot) => { - console.info("tanamUser snapshot :: ", snapshot.exists) - if (!snapshot.exists()) { setError(new UserNotification("error", "Access Denied", "Sorry you cant access the page")); } const tanamUser = TanamUserClient.fromFirestore(snapshot); - console.info("tanamUser :: ", tanamUser) setData(tanamUser); }, (err) => { From 76aad2e544918c0438f44c7d908f0c6e69b94ca6 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 16:54:36 +0700 Subject: [PATCH 06/17] redirect to error page when user doesnt have docid --- hosting/src/app/(protected)/layout.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/hosting/src/app/(protected)/layout.tsx b/hosting/src/app/(protected)/layout.tsx index 56371805..0f397066 100644 --- a/hosting/src/app/(protected)/layout.tsx +++ b/hosting/src/app/(protected)/layout.tsx @@ -1,20 +1,29 @@ "use client"; import CmsLayout from "@/components/Layouts/CmsLayout"; +import { useAuthentication } from "@/hooks/useAuthentication"; +import { useTanamUser } from "@/hooks/useTanamUser"; +import { redirect, usePathname } from "next/navigation"; import React from "react"; -import {useAuthentication} from "@/hooks/useAuthentication"; -import {redirect} from "next/navigation"; interface ProtectedLayoutProps { children: React.ReactNode; } export default function ProtectedLayout({children}: ProtectedLayoutProps) { - const {isSignedIn} = useAuthentication(); + const pathname = usePathname(); + const {isSignedIn, authUser} = useAuthentication(); + const {error: userError} = useTanamUser(authUser?.uid); + + console.info("pathname :: ", pathname) if (isSignedIn === false) { redirect("/"); } + if (pathname !== "/error" && userError && userError.message) { + redirect("/error"); + } + return {children}; } From ce299e22fdb39e31c036fec61eb886d44bba1b0b Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 16:57:26 +0700 Subject: [PATCH 07/17] move the redirect process in header --- hosting/src/app/(protected)/layout.tsx | 14 ++------------ hosting/src/components/Header/index.tsx | 9 +++++---- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/hosting/src/app/(protected)/layout.tsx b/hosting/src/app/(protected)/layout.tsx index 0f397066..1363c7b8 100644 --- a/hosting/src/app/(protected)/layout.tsx +++ b/hosting/src/app/(protected)/layout.tsx @@ -1,9 +1,7 @@ "use client"; - import CmsLayout from "@/components/Layouts/CmsLayout"; import { useAuthentication } from "@/hooks/useAuthentication"; -import { useTanamUser } from "@/hooks/useTanamUser"; -import { redirect, usePathname } from "next/navigation"; +import { redirect } from "next/navigation"; import React from "react"; interface ProtectedLayoutProps { @@ -11,19 +9,11 @@ interface ProtectedLayoutProps { } export default function ProtectedLayout({children}: ProtectedLayoutProps) { - const pathname = usePathname(); - const {isSignedIn, authUser} = useAuthentication(); - const {error: userError} = useTanamUser(authUser?.uid); - - console.info("pathname :: ", pathname) + const {isSignedIn} = useAuthentication(); if (isSignedIn === false) { redirect("/"); } - if (pathname !== "/error" && userError && userError.message) { - redirect("/error"); - } - return {children}; } diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index e3ae10d2..a4140053 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -3,16 +3,17 @@ import DropdownUser from "@/components/Header/DropdownUser"; import { useAuthentication } from "@/hooks/useAuthentication"; import Image from "next/image"; import Link from "next/link"; -import { useEffect } from "react"; +import { redirect, usePathname } from "next/navigation"; import { useTanamUser } from "../../hooks/useTanamUser"; const Header = (props: {sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void}) => { + const pathname = usePathname(); const {authUser} = useAuthentication(); const {data: tanamUser, error: userError} = useTanamUser(authUser?.uid); - useEffect(() => { - console.log("userError", userError); - }, [userError]); + if (pathname !== "/error" && userError && userError.message) { + redirect("/error"); + } return (
From ef7984e724837ac784a2b819ef727fcb84de2db3 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 16:58:20 +0700 Subject: [PATCH 08/17] remove unused --- hosting/src/plugins/firebase.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/hosting/src/plugins/firebase.ts b/hosting/src/plugins/firebase.ts index b0df01fd..e95a7258 100644 --- a/hosting/src/plugins/firebase.ts +++ b/hosting/src/plugins/firebase.ts @@ -1,5 +1,5 @@ import { initializeApp } from "firebase/app"; -import { connectAuthEmulator, getAuth } from "firebase/auth"; +import { getAuth } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { @@ -15,10 +15,3 @@ const firebaseConfig = { export const firebaseApp = initializeApp(firebaseConfig); export const firebaseAuth = getAuth(firebaseApp); export const firestore = getFirestore(firebaseApp); - -console.info('process.env.NEXT_ENV :: ', process.env.NEXT_ENV) - -// Connect to the emulator -if (process.env.NEXT_ENV === "local") { - connectAuthEmulator(firebaseAuth, process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ?? "http://localhost:9099") -} From 7109423adc006f399bdcad3cd872c7ef550f8305 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 17:01:38 +0700 Subject: [PATCH 09/17] update error page --- hosting/src/app/(protected)/error/page.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hosting/src/app/(protected)/error/page.tsx b/hosting/src/app/(protected)/error/page.tsx index 15973ec3..3c144212 100644 --- a/hosting/src/app/(protected)/error/page.tsx +++ b/hosting/src/app/(protected)/error/page.tsx @@ -1,8 +1,10 @@ "use client"; +import Loader from "@/components/common/Loader"; import Notification from "@/components/common/Notification"; import PageHeader from "@/components/common/PageHeader"; import { useAuthentication } from "@/hooks/useAuthentication"; import { useTanamUser } from "@/hooks/useTanamUser"; +import { Suspense } from "react"; export default function ErrorPage() { const {authUser} = useAuthentication(); @@ -10,12 +12,14 @@ export default function ErrorPage() { return ( <> - - + }> + + + ); } From a8ca876f524dcd6b97c1cf5d878d3cbfc4b5be55 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Mon, 29 Jul 2024 17:07:27 +0700 Subject: [PATCH 10/17] fix lint --- hosting/src/app/(protected)/error/page.tsx | 6 +++--- hosting/src/app/(protected)/layout.tsx | 4 ++-- hosting/src/components/Header/index.tsx | 6 +++--- hosting/src/hooks/useFirebaseUi.tsx | 12 +++++------- hosting/src/hooks/useTanamUser.tsx | 10 +++++----- hosting/src/plugins/firebase.ts | 6 +++--- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/hosting/src/app/(protected)/error/page.tsx b/hosting/src/app/(protected)/error/page.tsx index 3c144212..60c102ce 100644 --- a/hosting/src/app/(protected)/error/page.tsx +++ b/hosting/src/app/(protected)/error/page.tsx @@ -2,9 +2,9 @@ import Loader from "@/components/common/Loader"; import Notification from "@/components/common/Notification"; import PageHeader from "@/components/common/PageHeader"; -import { useAuthentication } from "@/hooks/useAuthentication"; -import { useTanamUser } from "@/hooks/useTanamUser"; -import { Suspense } from "react"; +import {useAuthentication} from "@/hooks/useAuthentication"; +import {useTanamUser} from "@/hooks/useTanamUser"; +import {Suspense} from "react"; export default function ErrorPage() { const {authUser} = useAuthentication(); diff --git a/hosting/src/app/(protected)/layout.tsx b/hosting/src/app/(protected)/layout.tsx index 1363c7b8..96eee477 100644 --- a/hosting/src/app/(protected)/layout.tsx +++ b/hosting/src/app/(protected)/layout.tsx @@ -1,7 +1,7 @@ "use client"; import CmsLayout from "@/components/Layouts/CmsLayout"; -import { useAuthentication } from "@/hooks/useAuthentication"; -import { redirect } from "next/navigation"; +import {useAuthentication} from "@/hooks/useAuthentication"; +import {redirect} from "next/navigation"; import React from "react"; interface ProtectedLayoutProps { diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index a4140053..9a8ea7ac 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -1,10 +1,10 @@ import DarkModeSwitcher from "@/components/Header/DarkModeSwitcher"; import DropdownUser from "@/components/Header/DropdownUser"; -import { useAuthentication } from "@/hooks/useAuthentication"; +import {useAuthentication} from "@/hooks/useAuthentication"; import Image from "next/image"; import Link from "next/link"; -import { redirect, usePathname } from "next/navigation"; -import { useTanamUser } from "../../hooks/useTanamUser"; +import {redirect, usePathname} from "next/navigation"; +import {useTanamUser} from "../../hooks/useTanamUser"; const Header = (props: {sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void}) => { const pathname = usePathname(); diff --git a/hosting/src/hooks/useFirebaseUi.tsx b/hosting/src/hooks/useFirebaseUi.tsx index 2daed6fe..dab985bf 100644 --- a/hosting/src/hooks/useFirebaseUi.tsx +++ b/hosting/src/hooks/useFirebaseUi.tsx @@ -1,9 +1,9 @@ "use client"; -import { firebaseAuth } from "@/plugins/firebase"; -import { AuthCredential, EmailAuthProvider, GoogleAuthProvider } from "firebase/auth"; -import { auth as firebaseAuthUi } from "firebaseui"; +import {firebaseAuth} from "@/plugins/firebase"; +import {AuthCredential, EmailAuthProvider, GoogleAuthProvider} from "firebase/auth"; +import {auth as firebaseAuthUi} from "firebaseui"; import "firebaseui/dist/firebaseui.css"; -import { useEffect, useState } from "react"; +import {useEffect, useState} from "react"; const firebaseUi = firebaseAuthUi.AuthUI.getInstance() || new firebaseAuthUi.AuthUI(firebaseAuth); @@ -33,9 +33,7 @@ export function useFirebaseUi() { signInOptions: [ { provider: EmailAuthProvider.PROVIDER_ID, - fullLabel: isSignUp - ? "Sign up with email" - : "Sign in with email" + fullLabel: isSignUp ? "Sign up with email" : "Sign in with email", }, { provider: GoogleAuthProvider.PROVIDER_ID, diff --git a/hosting/src/hooks/useTanamUser.tsx b/hosting/src/hooks/useTanamUser.tsx index d7c6f81b..82fc68a0 100644 --- a/hosting/src/hooks/useTanamUser.tsx +++ b/hosting/src/hooks/useTanamUser.tsx @@ -1,8 +1,8 @@ -import { TanamUserClient } from "@/models/TanamUserClient"; -import { UserNotification } from "@/models/UserNotification"; -import { firestore } from "@/plugins/firebase"; -import { doc, onSnapshot } from "firebase/firestore"; -import { useEffect, useState } from "react"; +import {TanamUserClient} from "@/models/TanamUserClient"; +import {UserNotification} from "@/models/UserNotification"; +import {firestore} from "@/plugins/firebase"; +import {doc, onSnapshot} from "firebase/firestore"; +import {useEffect, useState} from "react"; interface UseTanamDocumentsResult { data: TanamUserClient | null; diff --git a/hosting/src/plugins/firebase.ts b/hosting/src/plugins/firebase.ts index e95a7258..33d95b3d 100644 --- a/hosting/src/plugins/firebase.ts +++ b/hosting/src/plugins/firebase.ts @@ -1,6 +1,6 @@ -import { initializeApp } from "firebase/app"; -import { getAuth } from "firebase/auth"; -import { getFirestore } from "firebase/firestore"; +import {initializeApp} from "firebase/app"; +import {getAuth} from "firebase/auth"; +import {getFirestore} from "firebase/firestore"; const firebaseConfig = { apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, From f1c0984ec3116f803fcff87ae175de11d6cb2621 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 09:49:46 +0700 Subject: [PATCH 11/17] remove yarn lock in gitignore --- functions/.gitignore | 3 +-- hosting/.gitignore | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/functions/.gitignore b/functions/.gitignore index 8032bda4..069d927c 100644 --- a/functions/.gitignore +++ b/functions/.gitignore @@ -8,5 +8,4 @@ typings/ # Node.js dependency directory node_modules/ -*.local -yarn.lock \ No newline at end of file +*.local \ No newline at end of file diff --git a/hosting/.gitignore b/hosting/.gitignore index bdbca36d..fd3dbb57 100644 --- a/hosting/.gitignore +++ b/hosting/.gitignore @@ -34,5 +34,3 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts - -yarn.lock From a592b53decc8af5fc7f250292d2cd6c6fd04a62a Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 10:55:58 +0700 Subject: [PATCH 12/17] add validation check custom claims --- .../error/insufficient-role/page.tsx | 25 +++++++++++++++++ hosting/src/app/(protected)/error/page.tsx | 11 ++------ hosting/src/components/Header/index.tsx | 12 ++------ hosting/src/hooks/useAuthentication.tsx | 28 +++++++++++++++++-- 4 files changed, 56 insertions(+), 20 deletions(-) create mode 100644 hosting/src/app/(protected)/error/insufficient-role/page.tsx diff --git a/hosting/src/app/(protected)/error/insufficient-role/page.tsx b/hosting/src/app/(protected)/error/insufficient-role/page.tsx new file mode 100644 index 00000000..8f250a78 --- /dev/null +++ b/hosting/src/app/(protected)/error/insufficient-role/page.tsx @@ -0,0 +1,25 @@ +"use client"; +import Loader from "@/components/common/Loader"; +import Notification from "@/components/common/Notification"; +import PageHeader from "@/components/common/PageHeader"; +import { useAuthentication } from "@/hooks/useAuthentication"; +import { useTanamUser } from "@/hooks/useTanamUser"; +import { Suspense } from "react"; + +export default function ErrorInsufficientRolePage() { + const {authUser} = useAuthentication(); + const {error: userError} = useTanamUser(authUser?.uid); + + return ( + <> + }> + + + + + ); +} diff --git a/hosting/src/app/(protected)/error/page.tsx b/hosting/src/app/(protected)/error/page.tsx index 60c102ce..957c52b0 100644 --- a/hosting/src/app/(protected)/error/page.tsx +++ b/hosting/src/app/(protected)/error/page.tsx @@ -2,22 +2,17 @@ import Loader from "@/components/common/Loader"; import Notification from "@/components/common/Notification"; import PageHeader from "@/components/common/PageHeader"; -import {useAuthentication} from "@/hooks/useAuthentication"; -import {useTanamUser} from "@/hooks/useTanamUser"; -import {Suspense} from "react"; +import { Suspense } from "react"; export default function ErrorPage() { - const {authUser} = useAuthentication(); - const {error: userError} = useTanamUser(authUser?.uid); - return ( <> }> diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index 9a8ea7ac..2302772b 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -1,19 +1,13 @@ import DarkModeSwitcher from "@/components/Header/DarkModeSwitcher"; import DropdownUser from "@/components/Header/DropdownUser"; -import {useAuthentication} from "@/hooks/useAuthentication"; +import { useAuthentication } from "@/hooks/useAuthentication"; import Image from "next/image"; import Link from "next/link"; -import {redirect, usePathname} from "next/navigation"; -import {useTanamUser} from "../../hooks/useTanamUser"; +import { useTanamUser } from "../../hooks/useTanamUser"; const Header = (props: {sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void}) => { - const pathname = usePathname(); const {authUser} = useAuthentication(); - const {data: tanamUser, error: userError} = useTanamUser(authUser?.uid); - - if (pathname !== "/error" && userError && userError.message) { - redirect("/error"); - } + const {data: tanamUser} = useTanamUser(authUser?.uid); return (
diff --git a/hosting/src/hooks/useAuthentication.tsx b/hosting/src/hooks/useAuthentication.tsx index 063740bc..40ec917c 100644 --- a/hosting/src/hooks/useAuthentication.tsx +++ b/hosting/src/hooks/useAuthentication.tsx @@ -1,11 +1,16 @@ "use client"; -import {firebaseAuth} from "@/plugins/firebase"; -import {User} from "firebase/auth"; -import {useEffect, useState} from "react"; +import { firebaseAuth } from "@/plugins/firebase"; +import { TanamRole } from "@functions/models/TanamUser"; +import { User } from "firebase/auth"; +import { redirect, usePathname } from "next/navigation"; +import { useEffect, useState } from "react"; export function useAuthentication() { + const pathname = usePathname(); + const [error, setError] = useState(null); const [authUser, setUser] = useState(null); + const [userRole, setUserRole] = useState(null); const [isSignedIn, setIsSignedIn] = useState(null); useEffect(() => { @@ -13,11 +18,27 @@ export function useAuthentication() { console.log("[onAuthStateChanged]", {user}); setUser(user); setIsSignedIn(!!user); + fetchUserRole(); }); return () => unsubscribe(); }, []); + async function fetchUserRole() { + try { + const idTokenResult = await firebaseAuth.currentUser?.getIdTokenResult() + + setUserRole((idTokenResult?.claims as {tanamRole: TanamRole}).tanamRole) + + // Redirect when user doesn have claims + if (pathname !== "/error/insufficient-role" && !userRole) { + redirect("/error/insufficient-role"); + } + } catch (error) { + setError(error as Error); + } + } + async function signout() { console.log("[signout]"); try { @@ -30,6 +51,7 @@ export function useAuthentication() { return { isSignedIn, authUser, + userRole, error, signout, setError, From a8d3a324a0a2ea053abf156d6aa1b4f28e2f05d9 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 11:40:34 +0700 Subject: [PATCH 13/17] fix inconsistency --- functions/src/triggers/users.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/src/triggers/users.ts b/functions/src/triggers/users.ts index a876e29e..b77fbdc1 100644 --- a/functions/src/triggers/users.ts +++ b/functions/src/triggers/users.ts @@ -48,7 +48,7 @@ export const onTanamUserCreated = onDocumentCreated("tanam-users/{docId}", async // Function to enforce role management on document update // This function will apply changes to custom claims when the role field is updated -export const onRoleChange = onDocumentUpdated("tanam-users/{docId}", async (event) => { +export const onTanamUserRoleChange = onDocumentUpdated("tanam-users/{docId}", async (event) => { const uid = event.params.docId; const beforeData = event?.data?.before.data(); const afterData = event?.data?.after.data(); From 827f797d1f845eb9f47ffd8f6e611c1b423e0157 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 13:28:50 +0700 Subject: [PATCH 14/17] specific error page for insufficient role --- .../src/app/(protected)/error/insufficient-role/page.tsx | 6 +++--- hosting/src/app/(protected)/error/page.tsx | 8 ++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/hosting/src/app/(protected)/error/insufficient-role/page.tsx b/hosting/src/app/(protected)/error/insufficient-role/page.tsx index 8f250a78..9f68ba91 100644 --- a/hosting/src/app/(protected)/error/insufficient-role/page.tsx +++ b/hosting/src/app/(protected)/error/insufficient-role/page.tsx @@ -2,9 +2,9 @@ import Loader from "@/components/common/Loader"; import Notification from "@/components/common/Notification"; import PageHeader from "@/components/common/PageHeader"; -import { useAuthentication } from "@/hooks/useAuthentication"; -import { useTanamUser } from "@/hooks/useTanamUser"; -import { Suspense } from "react"; +import {useAuthentication} from "@/hooks/useAuthentication"; +import {useTanamUser} from "@/hooks/useTanamUser"; +import {Suspense} from "react"; export default function ErrorInsufficientRolePage() { const {authUser} = useAuthentication(); diff --git a/hosting/src/app/(protected)/error/page.tsx b/hosting/src/app/(protected)/error/page.tsx index 957c52b0..ba7ce983 100644 --- a/hosting/src/app/(protected)/error/page.tsx +++ b/hosting/src/app/(protected)/error/page.tsx @@ -2,18 +2,14 @@ import Loader from "@/components/common/Loader"; import Notification from "@/components/common/Notification"; import PageHeader from "@/components/common/PageHeader"; -import { Suspense } from "react"; +import {Suspense} from "react"; export default function ErrorPage() { return ( <> }> - + ); From 7064ec8b9fb08cdd60a25838e069e70da5cc4466 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 13:29:56 +0700 Subject: [PATCH 15/17] add functionality for get user role --- hosting/src/components/Header/index.tsx | 2 +- hosting/src/hooks/useAuthentication.tsx | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index 2302772b..49898dac 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -1,9 +1,9 @@ import DarkModeSwitcher from "@/components/Header/DarkModeSwitcher"; import DropdownUser from "@/components/Header/DropdownUser"; import { useAuthentication } from "@/hooks/useAuthentication"; +import { useTanamUser } from "@/hooks/useTanamUser"; import Image from "next/image"; import Link from "next/link"; -import { useTanamUser } from "../../hooks/useTanamUser"; const Header = (props: {sidebarOpen: string | boolean | undefined; setSidebarOpen: (arg0: boolean) => void}) => { const {authUser} = useAuthentication(); diff --git a/hosting/src/hooks/useAuthentication.tsx b/hosting/src/hooks/useAuthentication.tsx index 40ec917c..82101e65 100644 --- a/hosting/src/hooks/useAuthentication.tsx +++ b/hosting/src/hooks/useAuthentication.tsx @@ -7,7 +7,7 @@ import { useEffect, useState } from "react"; export function useAuthentication() { const pathname = usePathname(); - + const [error, setError] = useState(null); const [authUser, setUser] = useState(null); const [userRole, setUserRole] = useState(null); @@ -26,12 +26,15 @@ export function useAuthentication() { async function fetchUserRole() { try { - const idTokenResult = await firebaseAuth.currentUser?.getIdTokenResult() - - setUserRole((idTokenResult?.claims as {tanamRole: TanamRole}).tanamRole) + const idTokenResult = await firebaseAuth.currentUser?.getIdTokenResult(); + + setUserRole((idTokenResult?.claims as {tanamRole: TanamRole}).tanamRole); + + console.info("userRole :: ", userRole); + console.info("idTokenResult :: ", idTokenResult); - // Redirect when user doesn have claims - if (pathname !== "/error/insufficient-role" && !userRole) { + // Redirect when user doesnt have claims + if (pathname !== "/error/insufficient-role" && (userRole === null || !userRole)) { redirect("/error/insufficient-role"); } } catch (error) { From 7980dcb97f0b106333d67dccfa5ce3a3c63430b4 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 13:30:32 +0700 Subject: [PATCH 16/17] fix lint --- hosting/src/components/Header/index.tsx | 4 ++-- hosting/src/hooks/useAuthentication.tsx | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hosting/src/components/Header/index.tsx b/hosting/src/components/Header/index.tsx index 49898dac..7e1ab75d 100644 --- a/hosting/src/components/Header/index.tsx +++ b/hosting/src/components/Header/index.tsx @@ -1,7 +1,7 @@ import DarkModeSwitcher from "@/components/Header/DarkModeSwitcher"; import DropdownUser from "@/components/Header/DropdownUser"; -import { useAuthentication } from "@/hooks/useAuthentication"; -import { useTanamUser } from "@/hooks/useTanamUser"; +import {useAuthentication} from "@/hooks/useAuthentication"; +import {useTanamUser} from "@/hooks/useTanamUser"; import Image from "next/image"; import Link from "next/link"; diff --git a/hosting/src/hooks/useAuthentication.tsx b/hosting/src/hooks/useAuthentication.tsx index 82101e65..f5c5a6dd 100644 --- a/hosting/src/hooks/useAuthentication.tsx +++ b/hosting/src/hooks/useAuthentication.tsx @@ -1,9 +1,9 @@ "use client"; -import { firebaseAuth } from "@/plugins/firebase"; -import { TanamRole } from "@functions/models/TanamUser"; -import { User } from "firebase/auth"; -import { redirect, usePathname } from "next/navigation"; -import { useEffect, useState } from "react"; +import {firebaseAuth} from "@/plugins/firebase"; +import {TanamRole} from "@functions/models/TanamUser"; +import {User} from "firebase/auth"; +import {redirect, usePathname} from "next/navigation"; +import {useEffect, useState} from "react"; export function useAuthentication() { const pathname = usePathname(); From ae3bdacd26ad5c377973e07fe8c61e3246b87ec8 Mon Sep 17 00:00:00 2001 From: Nurfirliana Muzanella Date: Tue, 30 Jul 2024 13:32:15 +0700 Subject: [PATCH 17/17] remove unused --- hosting/src/hooks/useAuthentication.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/hosting/src/hooks/useAuthentication.tsx b/hosting/src/hooks/useAuthentication.tsx index f5c5a6dd..f5c47a82 100644 --- a/hosting/src/hooks/useAuthentication.tsx +++ b/hosting/src/hooks/useAuthentication.tsx @@ -30,9 +30,6 @@ export function useAuthentication() { setUserRole((idTokenResult?.claims as {tanamRole: TanamRole}).tanamRole); - console.info("userRole :: ", userRole); - console.info("idTokenResult :: ", idTokenResult); - // Redirect when user doesnt have claims if (pathname !== "/error/insufficient-role" && (userRole === null || !userRole)) { redirect("/error/insufficient-role");