Firebase를 이용한 어드민 수락 기반 회원가입 구현하기

서정우·2024년 5월 25일
2

프리미티브 동아리 홈페이지를 제작하면서 몇 가지 기능을 추가하고자 Firebase를 사용하기로 결정했다.

아무래도 동아리 홈페이지의 로그인 방식이기 때문에 누구나 회원가입을 하는 것보다 인증된 사용자만 회원가입이 되게끔 하고 싶어서 어드민 수락 기반 인증 방법을 구현하기로 했다.

어드민 수락 기반 회원가입

어드민 페이지 🐔

우선, 동아리 운영자만 접근할 수 있는 페이지를 만들어야 했다. 회원가입 여부를 결정하는 페이지이기 때문에 현재 유저가 로그인 되어있는지와 되어있다면 권한 등급이 어떤지를 검사하는 함수로 접근을 제한했다.

// 어드민 체크
  const checkAdmin = async () => {
    const auth = getAuth();
    onAuthStateChanged(auth, async (user) => {
      if (user) {
        const uid = user.uid;
        const userRef = doc(db, "users", uid);
        const userDoc = await getDoc(userRef);
        const authority = userDoc.data().authority;
        if (authority === "관리자" || authority === "회장" || authority === "부회장")
          setIsAdmin(true);
      } else {
        setIsAdmin(false);
      }
    });
  };

신규 유저의 가입 요청 수락하기 🐥

유저가 회원가입을 시도하면 회원가입 요청 컬렉션에 요청 데이터를 저장하고 어드민은 이를 수락할지 거절할지를 결정할 수 있도록 하였다.

수락시에는 요청 데이터를 기반으로 회원가입을 진행하도록 했다. 하지만 여기서 큰 문제가 발생하는데.....


  // 수락 핸들러
  const onApprove = async (member) => {
    try {
      try {
        // 회원가입 진행 절차
        const auth = getAuth();
        const result = await createUserWithEmailAndPassword(auth, member.email, member.password);
        const userRef = doc(db, "users", result.user.uid);

        await setDoc(userRef, {
          email: member.email,
          username: member.username,
          studentYear: member.studentYear,
          authority: "동아리원",
          status: "Active",
        });
      } catch (e) {
        console.error("회원가입 중 오류 발생", e);
      }

      // signupRequests 컬렉션의 상태를 'accepted'로 업데이트
      const requestRef = doc(db, "signupRequests", member.id);
      await updateDoc(requestRef, {
        status: "approved",
      });

      // 상태 업데이트 
      setRequests((prevRequests) => prevRequests.filter((req) => req.id !== member.id));
    } catch (error) {
      console.error(error);
    }
  };

바로 어드민이 요청 수락을 하는 순간

createUserWithEmailAndPassword 메서드로 회원가입을 진행하는데.... 이 메서드는 가입하고 로그인도 동시에 진행한다!!!!

이 자식 때문에 어드민 세션이 새로 가입되는 유저로 덮어쓰여져 아래처럼 어드민 계정이 로그아웃 되는 문제였다...

해결하기

이를 해결하기 위해서는 firebase 를 초기화하는 단계에서 app을 하나 더 만들어서 회원가입 용으로 만드는 방법을 사용했다.

회원가입 후 로그인을 자동으로 안하는 메서드 같은건 없다...

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const adminApp = initializeApp(firebaseConfig, "Admin");
export const db = getFirestore(app);
export const storage = getStorage(app);
export const auth = getAuth(app);
export default app;

일반적으로 firebase를 사용하는데에는 첫 줄의 app을 사용한다. 하지만 회원가입을 진행할 때는 adminApp 이름으로 파이어베이스 인스턴스를 하나 더 초기화해준다.

그 후 export 해주면 회원가입을 진행할 때에만 해당 인스턴스를 사용하면 해당 인스턴스가 새로운 유저로 로그인되겠지만 다른 곳에서 사용하지 않는 회원가입 전용 객체이기 때문에 전혀 문제가 없다.

// 회원가입 진행 절차
const auth = getAuth(adminApp); // adminApp을 전달
const result = await createUserWithEmailAndPassword(auth, member.email, member.password);
const userRef = doc(db, "users", result.user.uid);

이 방식으로 수정하면 이제 어드민이 수락을 해도 어드민 로그인 세션을 유지하면서 신규 유저의 회원가입을 진행할 수 있게 된다.

참고

Firebase kicks out current user <- 감사합니다 ㅠㅠ

profile
프론트엔드 개발자 시켜주세요..

0개의 댓글