Vue PWA mylog Source Code

store/auth.js

그랜파 개발자 2024. 11. 9. 06:17

store/modules/auth.js

// src/store/modules/auth.js
import router from '@/router';  // Vue Router import
import { auth, db, collection, doc, getDocs, addDoc, updateDoc, arrayUnion, query, where } from "@/firebase";
import { createUserWithEmailAndPassword, signInWithEmailAndPassword, onAuthStateChanged, sendPasswordResetEmail, 
  EmailAuthProvider, reauthenticateWithCredential, updatePassword, GoogleAuthProvider, signInWithPopup  } from "firebase/auth";

const state = {
  isLoading: false,
  error: null,
  user: null, // 현재 로그인한 회원
  users: [],  // 전체 회원 정보
};

const mutations = {
  setLoading(state, isLoading) {
    state.isLoading = isLoading;
  },
  setError(state, error) {
    state.error = error;
  },
  setUser(state, user) {
    state.user = user;
  },
  setUsers(state, users) {
    state.users = users;
  },
};

const actions = {
  // -- 앱을 시작하면 자동 로그인을 설정한다.
  async initializeAuth({ commit, dispatch }) {
    onAuthStateChanged(auth, (user) => {
      if (user) {
        // user.uid로 웹앱의 firestore DB에서 계정 정보를 가져온다.
        dispatch('fetchUserWithUid', {uid: user.uid});
      } else {
        commit("setUser", null);
      }
    });
  },

  // 전체 회원 정보를 로드한다.
  async fetchUsers({ commit }) {
    commit('setLoading', true);
    try {
      const users = [];
      const userRef = collection(db, "users");
      const querySnapshot = await getDocs(userRef);
      querySnapshot.forEach((doc) => {
        // doc.data() is never undefined for query doc snapshots
        users.push({ id: doc.id, ...doc.data() });
      });
      commit('setUsers', users);
    } catch (error) {
      commit('setError', error.message);
    } finally {
      commit('setLoading', false);
    }
  },

  // -- 계정 만들기
  async register({ commit, dispatch }, { email, password, username, mylogname }) {
    try {
      const userCredential = await createUserWithEmailAndPassword(auth, email, password);
      const uid = userCredential.user.uid;

      // Save additional user data to Firestore
      const userRef = collection(db, "users");
      const newUser = await addDoc(userRef, {
        email: email,
        uids: [uid],
        username: username,
        mylogname: mylogname
      });

      // 로그인 설정
      commit('setUser', newUser);
      dispatch('fetchUsers');

      router.push("/");   // home으로

    } catch (error) {
      commit("setError", error.message);
    }
  },

  // -- 로그인 
  async login({ commit, dispatch }, { email, password }) {    
    try {
      const { user } = await signInWithEmailAndPassword(auth, email, password);      
      // 웹앱의 계정 정보를 가져와 로그인 설정을 한다.
      dispatch('fetchUserWithUid', {uid: user.uid});
      router.push("/");   // home으로
    } catch (error) {
      //commit('setError', error.message);
      alert("Failed to log in: " + error.message);
    }
  },

  // 로그인은 google 계정으로 한다.user 정보는 mylog 계정 정보를 사용한다.
  // 그러므로 구글 계정의 uid로 mylog 계정의 user 정보를 가져와야 한다.
  async fetchUserWithUid({ commit, dispatch }, {uid}) {    
    try {
      const users = []; 
      const userRef = query(collection(db, "users"), where('uids', 'array-contains', uid));
      const querySnapshot = await getDocs(userRef);
      querySnapshot.forEach((doc) => {
        // doc.data() is never undefined for query doc snapshots
         users.push({ id: doc.id, ...doc.data() });
      });
      // 로그인 설정을 한다.
      commit('setUser', users[0]);
    } catch (error) {
      console.error('Error fetching user:', error);
    }            
  },

  // 로그아웃 --
  async logout({ commit }) {
    await auth.signOut();
    commit('setUser', null);
  },

  // 비밀번호 재설정
  async PasswordReset({}, email) {  
    console.log(email);
    sendPasswordResetEmail(auth, email)
    .then(() => {
      alert("비밀번호 재설정 이메일이 발송되었습니다.");
    })
    .catch((error) => {
      alert("비밀번호 재설정 이메일 발송 중 오류 발생:", error);
    });
  },

  // 비밀번호 변경
  async changePassword({}, { oldPassword, newPassword }) {  
    const credential = EmailAuthProvider.credential(
      auth.currentUser.email,
      oldPassword
    );

    reauthenticateWithCredential(auth.currentUser, credential)
    .then(() => {
      updatePassword(auth.currentUser, newPassword)
      .then(() => {
        alert("비밀번호가 성공적으로 변경되었습니다.");
      }).catch((error) => {
        alert("비밀번호 변경 실패 : " + error.message);
      });
    })
    .catch((error) => {
      alert("재인증 실패 : " + error.message);
    });
  },

  // 계정 정보 수정
  async updateUserInfo({ commit }, updatedInfo) {
    try {
      const userDoc = doc(db, "users", updatedInfo.id);
      await updateDoc(userDoc, updatedInfo);

      commit("setUser", updatedInfo);

      alert("계정 정보를 수정하였습니다.");
    } catch (error) {
      alert("계정 정보 수정 실패: " + error.message);
    }
  },

  async addGoogleAccount({ commit, dispatch, getters }) {
    try {
      const provider = new GoogleAuthProvider();
      const { user } = await signInWithPopup(auth, provider);
      try {
        // 이미 연동된 회원의 경우 알림 메시지 출력한다.
        const uid = user.uid;
        const myUser = state.users.find(user => user.uids && user.uids.includes(uid));
        if (myUser) {
          // 이미 연동되어 있다.
          alert('이미 연동되어 있습니다.');
        } else {
          // 구글 연동을 진행한다.
          dispatch('addUidToUser', user.uid);
        }          
      } catch (error) {
        commit('setError','Error adding google uid');
      }
    } catch (error) {
      commit('setError', error.message);
    }
  },

  // 구글 계정의 uid를 받아 user collection의 uids에 넣는다.
  async addUidToUser({ state }, newUid) {      
    //console.log('user.id:', state.user.id);
    if (state.user) {
      try {
        const userDoc = doc(db, "users", state.user.id);
        updateDoc(userDoc, {
          uids: arrayUnion(newUid)
        });
        // Update the local state if neededa
        state.user.uids = [...(state.user.uids || []), newUid];
      } catch (error) {
        console.error('Error adding UID to user:', error);
      }
    }
  },

  // 구글 계정으로 로그인
  async googleLogin({ commit }) {
    try {
      // 구글 계정에 로그인
      const provider = new GoogleAuthProvider();
      const { user } = await signInWithPopup(auth, provider);

      // 구글계정의 uid로 웹앱 계정의 정보를 가져옴.
      // 웹앱 계정은 사이트에 접속할 때 전체 회원 정보를 로드하였으므로 
      // 이미 로드된 회원 리스트에서 구글 계정 uid를 가진 myUser를 가져온다.
      const uid = user.uid;
      const myUser = state.users.find(user => user.uids && user.uids.includes(uid));
      if (myUser) {
        commit('setUser', myUser);
        router.push("/");   // home으로
      } else {
        alert('등록된 회원이 아닙니다.');
      }

    } catch (error) {
      commit('setError', error.message);
    }
  },

  resetError({ commit }) {
    commit('setError', null);
  },
};

const getters = {
  isLoading: state => state.isLoading,
  error: state => state.error,
  user: state => state.user, 
  users: state => state.users,
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
};

'Vue PWA mylog Source Code' 카테고리의 다른 글

store/mylogs.js  (0) 2024.11.11
store/fcm.js  (0) 2024.11.09
store/index.js  (0) 2024.11.09
router  (0) 2024.11.08
firebase.js  (0) 2024.11.07