fibase 문서 참조
1) https://firebase.google.com/docs/auth/web/password-auth?hl=ko
2) https://firebase.google.com/docs/auth/web/google-signin?hl=ko
3) 백엔드 서버 nodejs functions 으로 회원 레벨 개발 처리
https://firebase.google.com/docs/auth/admin/custom-claims?hl=ko
* 회원가입 및 로그인 중요한 코드 내용은 다음 내용이다.
// 구글 인증으로 가입시
async signInWithGoogle() {
const provider = this.$provider;
const auth = this.$auth;
auth.languageCode = 'ko';
//1.구글 인증 (인증과 동시에 firebase 의 Authentication 에 등록되어 있지않으면 등록처리된다.)
//등록시 fireabse functions 커스텀등록을 통해 에 유저 level 설정 할수 있다.
//참조 : https://firebase.google.com/docs/auth/admin/custom-claims?hl=ko
// 백엔드 서버 노드js function 개발 : exports.processSignUp = functions.auth.user().onCreate(async (user)
await this.$signInWithPopup(auth, provider);
//2.현재 토큰 정보가져오기 - getIdTokenResult true 를해야 토큰값이 갱신된다.
const user= await auth.currentUser.getIdTokenResult(true);
//3.firebase store 또는 DB에 유저정보 확인
const confirmUser= await this.$fbGetData("members", user.claims.email);
if(confirmUser.data()==undefined){
//confirmUser
//4. firebase store 또는 기타 mysql DB 등에 에 유저 정보 저장 - 아이디는 이메이로) 예 claims.email
await this.$fbWriteSetDoc("members", user.claims.email, user.claims);
//store. 인증처리 결과르 확인을 위한 vue 프론트의 임의 변수에 저장 처리
await this.$store.dispatch('setClaims', user.claims);
}
//store에 레벨값이 들어올 때까지 기다린다.
const accessLevel=await this.$store.state.claims.accessLevel;
if(accessLevel){
this.$router.push("/");
}
},
//회원가입
async memberJoin(){
console.log("memberJoin 2 ");
if(!this.$refs.form.validate()) return this.$toasted.global.error('입력폼을 올바르게 작성해 주세요.');
const auth = this.$auth;
auth.languageCode = 'ko';
//1. Authentication 에회원 이메일 비밀번호 최초등록 (기타 정보는 업데이트 처리 되지않는다.) 및 로그인 처리된다.
//firebase functions 함수로 회원레벨 설정 함수가 등록되었을 시에 회원가입과 함께 회원레벨이 등록되어진다.
await this.$createUserWithEmailAndPassword(auth, this.form.email, this.form.password);
// 2. Authentication 에 이메일과 비밀번호 밖에 등록이 안되기 때문에 displayName 업데이트 및 photoURL 업데이트 처리한다.
await this.$updateProfile(this.$auth.currentUser, {
displayName: this.form.lastName + this.form.firstName , photoURL: ""
});
//3.현재 토큰 정보가져오기 - getIdTokenResult true 를해야 토큰값이 갱신된다.
const user= await auth.currentUser.getIdTokenResult(true);
//4.firebase store 또는 DB에 유저정보 확인
const confirmUser= await this.$fbGetData("members", user.claims.email);
if(confirmUser.data()==undefined){
//5. firebase store 또는 기타 mysql DB 등에 에 유저 정보 저장 - 아이디는 이메이로) 예 claims.email
await this.$fbWriteSetDoc("members", user.claims.email, user.claims);
//store. 인증처리 결과르 확인을 위한 vue 프론트의 임의 변수에 저장 처리
await this.$store.dispatch('setClaims', user.claims);
}
//store에 레벨값이 들어올 때까지 기다린다.
const accessLevel=await this.$store.state.claims.accessLevel;
if(accessLevel){
this.$router.push("/");
}
},
//이메일과 비번으로 로그인시
async signInEmail(email, password) {
try {
await this.$signInWithEmailAndPassword(this.$auth, email, password);
} catch (error) {
if(error.toString().indexOf('auth/wrong-password') !==-1){
this.$toasted.global.error("아이디 또는 비밀번호가 일치하지 않습니다.");
}else if(error.toString().indexOf('auth/user-not-found') !==-1){
this.$toasted.global.error("등록된 회원이 아닙니다.");
}else{
this.$toasted.global.error(error.toString());
}
}
},
//로그아웃
async signOut() {
await this.$signOut(this.$auth);
},
백엔드 서버 nodejs functions
//등록 처리시
exports.createUser = functions.auth.user().onCreate(async (user) => {
let customClaims = {
admin: false,
accessLevel: 1
};
if (user.email && user.email.endsWith('braverokmc79@gmail.com') && user.emailVerified) {
//관리자일경우
customClaims = {
admin: true,
accessLevel: 9
};
}
await getAuth().setCustomUserClaims(user.uid, customClaims);
});
전체
https://firebase.google.com/docs/auth/web/password-auth?hl=ko&authuser=0
import { initializeApp } from "firebase/app";
import { signInWithPopup, GoogleAuthProvider, initializeAuth,
browserSessionPersistence, browserPopupRedirectResolver } from "firebase/auth";
const firebaseConfig = {
...
};
const firebaseApp = initializeApp(firebaseConfig);
const auth = initializeAuth(firebaseApp, {
persistence: browserSessionPersistence,
popupRedirectResolver: browserPopupRedirectResolver,
});
const provider = new GoogleAuthProvider();
signInWithPopup(auth, provider)
.then((result) => {
...
});
firebase.js
import "firebase/auth";
import "firebase/firestore";
import Vue from 'vue'
import * as firebase from 'firebase/app';
import { initializeApp } from 'firebase/app';
//import firebase from "firebase/app";
import { query, orderBy, startAfter, limit, endBefore, limitToLast } from "firebase/firestore";
import { getFirestore, collection, getDocs, serverTimestamp, addDoc, doc, getDoc, updateDoc, deleteDoc, setDoc } from 'firebase/firestore';
import firebaseConfig from '../../firebaseConfig.js';
import { head } from 'lodash'
import store from "../store/index.js";
import router from '../router'
//구글 로그인 인증
import {
signInWithPopup, GoogleAuthProvider, initializeAuth,
browserSessionPersistence, browserPopupRedirectResolver, createUserWithEmailAndPassword,
signInWithEmailAndPassword, onAuthStateChanged, signOut, updateProfile
//getAuth
} from "firebase/auth";
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
const auth = initializeAuth(app, {
persistence: browserSessionPersistence,
popupRedirectResolver: browserPopupRedirectResolver,
});
const provider = new GoogleAuthProvider();
//에뮬레이터 Firestore 사용시 다음 두줄 주석해제
//import { connectFirestoreEmulator } from "firebase/firestore";
//connectFirestoreEmulator(db, 'localhost', 8080);
//메시지 앱 푸시
//import { getMessaging } from "firebase/messaging";
//const messaging = getMessaging(app);
//collectionName => table 이름
//1. 아이디 자동 생성 firebase 저장하기
async function fbWrite(collectionName, objData) {
//firebase 데이터 저장 - addDoc 일경우 아이디가 자동 생성
await addDoc(collection(getFirestore(), collectionName), objData);
// 전체등록 갯수 가져오기
const docRef = doc(db, collectionName + "_totalCount", "tot_id");
const totNum = await getDoc(docRef);
//전체등록 갯수 업데이트 // totNum.exists() 존재할 경우 업데이트 처리 - 카운트 증가처리 : 없으면 1 로 최초등록
await setDoc(doc(db, collectionName + "_totalCount", "tot_id"), {
totalCount: totNum.exists() ? totNum.data().totalCount + 1 : 1,
upDate: serverTimestamp()
});
}
//아이디가 존재할 경우
async function fbWriteSetDoc(collectionName, id, objData) {
//firebase 데이터 저장 - setDoc 일경우 아이디가 자동 생성
await setDoc(doc(db, collectionName, id), objData);
// 전체등록 갯수 가져오기
const docRef = doc(db, collectionName + "_totalCount", "tot_id");
const totNum = await getDoc(docRef);
//전체등록 갯수 업데이트 // totNum.exists() 존재할 경우 업데이트 처리 - 카운트 증가처리 : 없으면 1 로 최초등록
await setDoc(doc(db, collectionName + "_totalCount", "tot_id"), {
totalCount: totNum.exists() ? totNum.data().totalCount + 1 : 1,
upDate: serverTimestamp()
});
}
//firebase 삭제하기
async function fbDelete(collectionName, id) {
await deleteDoc(doc(db, collectionName, id));
// 전체등록 갯수 가져오기
const docRef = doc(db, collectionName + "_totalCount", "tot_id");
const totNum = await getDoc(docRef);
//전체 갯수 업데이트 // totNum.docs[0] 값이 없을 경우 최초 등록으로 1 , 존재할 경우 업데이트 처리 - 카운트 감소
await setDoc(doc(db, collectionName + "_totalCount", "tot_id"), {
totalCount: totNum.data().totalCount > 0 ? totNum.data().totalCount - 1 : 0,
upDate: serverTimestamp()
});
}
//firebase 수정하기
async function fbUpdate(collectionName, objData) {
const updateData = doc(db, collectionName, objData.id);
await updateDoc(updateData, objData);
}
//firebase 한개의 데이터 가져오기
async function fbGetData(collectionName, id) {
const docRef = doc(db, collectionName, id);
return await getDoc(docRef);
}
// firebase 데이터 목록 가져오기
async function fbGetList(collectionName) {
const querySnapshot = await getDocs(collection(db, collectionName));
return querySnapshot;
}
// firebase query 데이터 목록 가져오기
async function fbGetQueryList(collectionName, culum, order, pageSize, documentSnapshots, currentPage, beforPage) {
//1. 첫 페이지일 경우
if (currentPage == undefined || currentPage == 1) {
//1.첫페이지일 경우
const first = query(collection(db, collectionName),
orderBy(culum, order),
limit(pageSize));
const documentSnapshots2 = await getDocs(first);
return documentSnapshots2;
}
if (beforPage <= currentPage) {
//2.next 다음 페이지로 이동
const lastVisible = documentSnapshots.docs[documentSnapshots.docs.length - 1];
if (documentSnapshots.size == 0) {
return;
}
const next = query(collection(db, collectionName),
orderBy(culum, order),
startAfter(lastVisible),
limit(pageSize));
const documentSnapshots2 = await getDocs(next);
return documentSnapshots2;
} else {
//3.이전 페이지로 이동
const prevVisible = documentSnapshots.docs;
const before = query(collection(db, collectionName),
orderBy(culum, order),
endBefore(head(prevVisible)),
limitToLast(pageSize + 1)
);
const documentSnapshots2 = await getDocs(before);
return documentSnapshots2;
}
}
Vue.prototype.$isFirebaseAuth = false;
// onAuthStateChanged(auth, (user) => {
// if(user){
// Vue.prototype.$isFirebaseAuth = true;
// router.push("/");
// } else {
// Vue.prototype.$isFirebaseAuth = false;
// router.push("/sign");
// }
// store.dispatch('getUser', user)
// });
onAuthStateChanged(auth, (user) => {
console.log("onAuthStateChanged : =>");
console.log(user);
store.dispatch('getUser', user)
.then(r => {
console.log("r : ");
console.log(JSON.stringify(r));
if (user) {
Vue.prototype.$isFirebaseAuth = true;
router.push("/");
} else {
//로그인 인증 안된경우
Vue.prototype.$isFirebaseAuth = false;
router.push("/sign");
}
});
});
//전역변수로 사용 설정
Vue.prototype.$firebase = firebase
Vue.prototype.$fbWrite = fbWrite
Vue.prototype.$fbWriteSetDoc = fbWriteSetDoc
Vue.prototype.$fbUpdate = fbUpdate
Vue.prototype.$fbGetList = fbGetList
Vue.prototype.$fbGetQueryList = fbGetQueryList
Vue.prototype.$fbDelete = fbDelete
Vue.prototype.$fbGetData = fbGetData
Vue.prototype.$db = db
Vue.prototype.$getFirestore = getFirestore
Vue.prototype.$collection = collection
Vue.prototype.$getDocs = getDocs
Vue.prototype.$serverTimestamp = serverTimestamp
Vue.prototype.$addDoc = addDoc
Vue.prototype.$doc = doc
Vue.prototype.$getDoc = getDoc
Vue.prototype.$updateDoc = updateDoc
Vue.prototype.$deleteDoc = deleteDoc
Vue.prototype.$signOut = signOut
Vue.prototype.$updateProfile = updateProfile
Vue.prototype.$onAuthStateChanged = onAuthStateChanged
Vue.prototype.$signInWithPopup = signInWithPopup
Vue.prototype.$GoogleAuthProvider = GoogleAuthProvider
Vue.prototype.$auth = auth
Vue.prototype.$provider = provider
Vue.prototype.$createUserWithEmailAndPassword = createUserWithEmailAndPassword
Vue.prototype.$signInWithEmailAndPassword = signInWithEmailAndPassword
1 . auth/signIn.vue
<template>
<v-card color="white" height="500">
<v-form v-model="valid" ref="form" lazy-validation>
<v-card-title primary-title text-md-center >
<span class="title" ><h2 style="font-weight:bold" >로그인</h2></span>
<v-spacer></v-spacer>
<span class="caption white">
<!-- <a class="mr-1" @click="$emit('type-change' , true)">로그인</a> -->
또는 <a class="mr-1" @click="$emit('type-change', false)">회원가입</a></span>
</v-card-title>
<v-card-actions justify-start>
<v-btn color="primary"
@click="$emit('signInWithGoogle')"
dark justify-start block class="pt-3 pb-3"
style="height: 45px; text-transform: none" >
<v-icon >mdi-google</v-icon>
<v-divider vertical class="mx-3"></v-divider>
Google 계정으로 로그인
</v-btn>
</v-card-actions>
<v-container grid-list-md fluid>
<v-layout row wrap>
<v-flex xs5>
<v-divider class="mt-2"></v-divider>
</v-flex>
<v-flex xs2 text-md-center>
또는
</v-flex>
<v-flex xs5 >
<v-divider class="mt-2"></v-divider>
</v-flex>
</v-layout>
</v-container>
<v-card-text>
<v-text-field label="이메일" v-model="email"
:rules="[rule.required, rule.email]"
></v-text-field>
<v-text-field label="비밀번호" v-model="password" type="password"
:rules="[rule.required]"
></v-text-field>
</v-card-text>
<div class="px-3 recaptcha-terms-text" >이 페이지는 reCAPTCHA로 보호되며, Google 개인정보처리방침 및 서비스 약관의 적용을 받습니다.</div>
<div class="px-3 recaptcha-terms-text" style="color:red; font-weight:bold" v-text="message"></div>
<v-card-actions>
<v-checkbox label="로그인 정보저장" ></v-checkbox>
<v-spacer></v-spacer>
<v-btn v-if="!$store.state.user"
color="primary" @click="signInEmail" :disabled="!valid">로그인</v-btn>
<v-btn v-else color="success" dark="dark" @click="$emit('signOut')">
<v-icon>mdi-logout</v-icon>
로그아웃
</v-btn>
</v-card-actions>
</v-form>
</v-card>
</template>
<script>
export default {
props:{
message:{
type:String,
required:false
}
},
data(){
return{
valid:true,
email:"",
password:"",
rule:{
required:v => !!v || '필수 항목 입니다.',
minLength:length => v => v.length >= length || `${length} 자리 이상 이여야 합니다.`,
maxLength:length => v => v.length <= length || `${length} 자리 이하 이여야 합니다.`,
email: v => /.+@.+/.test(v) || '이메일 형식에 맞지 않습니다.',
passwordConfirm: v => v === this.form.password || ` 패스워드가 일치하지 않습니다.`,
agree: v=> !!v || '약관에 동의해야 가입 가능합니다.'
}
}
},
computed:{
},
methods:{
signInEmail(){
console.log("이메일 값 : " + this.email);
this.$emit('signInEmail', this.email, this.password);
}
}
}
</script>
<style scoped>
.recaptcha-terms-text{
font-size: 14px;
font-weight: 200;
color: #637282;
font-family: 'Noto Sans KR', sans-serif;
font-weight: 400;
}
</style>
2. auth/signUp.vue
!<template>
<v-card color="white" height="auto">
<v-form v-model="valid" ref="form" lazy-validation>
<v-card-title primary-title text-md-center >
<span class="title" ><h2 style="font-weight:bold" >회원가입</h2></span>
<v-spacer></v-spacer>
<span class="caption white">
<!-- <a class="mr-1" @click="$emit('type-change' , true)" >로그인</a> -->
또는 <a class="mr-1" @click="$emit('type-change', true)">로그인</a></span>
</v-card-title>
<v-container grid-list-md fluid>
<v-layout row wrap>
<v-flex xs5>
<v-divider class="mt-2"></v-divider>
</v-flex>
<v-flex xs2 text-md-center>
또는
</v-flex>
<v-flex xs5 >
<v-divider class="mt-2"></v-divider>
</v-flex>
</v-layout>
</v-container>
<v-card-actions justify-start>
<v-btn color="primary"
@click="signInWithGoogle"
dark justify-start block class="pt-3 pb-3"
style="height: 45px; text-transform: none" >
<v-icon >mdi-google</v-icon>
<v-divider vertical class="mx-3"></v-divider>
Google 계정으로 가입
</v-btn>
</v-card-actions>
<v-card-text>
<v-text-field label="성" v-model="form.lastName" class="mb-3"
:rules="[rule.required, rule.minLength(1), rule.maxLength(2)]"
></v-text-field>
<v-text-field label="이름" v-model="form.firstName" class="mb-3"
:rules="[rule.required, rule.minLength(1), rule.maxLength(10)]"
></v-text-field>
<v-text-field label="이메일" v-model="form.email"
:rules="[rule.required, rule.email ,rule.minLength(7), rule.maxLength(50)]"
class="mb-3"></v-text-field>
<v-text-field label="비밀번호" v-model="form.password" type="password" class="mb-3"
:rules="[rule.required,rule.minLength(6), rule.maxLength(50)]"
></v-text-field>
<v-text-field label="비밀번호확인" v-model="form.passwordConfirm" type="password" class="mb-3"
:rules="[rule.required, rule.passwordConfirm]"
></v-text-field>
</v-card-text>
<div class="px-3 recaptcha-terms-text" >이 페이지는 reCAPTCHA로 보호되며,
Google 개인정보처리방침 및 서비스 약관의 적용을 받습니다.</div>
<div class="px-3 recaptcha-terms-text" style="color:red; font-weight:bold" v-text="message"></div>
<v-card-actions>
<v-checkbox label="약관에 동의함" :rules=[rule.agree] required></v-checkbox>
<v-spacer></v-spacer>
<v-btn color="primary" @click="memberJoin" :disabled="!valid">회원가입</v-btn>
</v-card-actions>
</v-form>
</v-card>
</template>
<script>
import { sendEmailVerification } from "firebase/auth";
export default {
props:{
},
data(){
return{
valid:true,
agree:false,
message:"",
form:{
firstName:'',
lastName:'',
email: '',
password: '',
passwordConfirm:'',
},
rule:{
required:v => !!v || '필수 항목 입니다.',
minLength:length => v => v.length >= length || `${length} 자리 이상 이여야 합니다.`,
maxLength:length => v => v.length <= length || `${length} 자리 이하 이여야 합니다.`,
email: v => /.+@.+/.test(v) || '이메일 형식에 맞지 않습니다.',
passwordConfirm: v => v === this.form.password || ` 패스워드가 일치하지 않습니다.`,
agree: v=> !!v || '약관에 동의해야 가입 가능합니다.'
}
}
},
methods:{
// 구글 인증
async signInWithGoogle() {
const provider = this.$provider;
const auth = this.$auth;
auth.languageCode = 'ko';
//1.구글 인증 (인증과 동시에 firebase 의 Authentication 에 등록되어 있지않으면 등록처리된다.)
//등록시 fireabse functions 커스텀등록을 통해 에 유저 level 설정 할수 있다.
//참조 : https://firebase.google.com/docs/auth/admin/custom-claims?hl=ko
// 백엔드 서버 노드js function 개발 : exports.processSignUp = functions.auth.user().onCreate(async (user)
await this.$signInWithPopup(auth, provider);
//2.현재 토큰 정보가져오기 - getIdTokenResult true 를해야 토큰값이 갱신된다.
const user= await auth.currentUser.getIdTokenResult(true);
//3.firebase store 또는 DB에 유저정보 확인
const confirmUser= await this.$fbGetData("members", user.claims.email);
if(confirmUser.data()==undefined){
//confirmUser
//4. firebase store 또는 기타 mysql DB 등에 에 유저 정보 저장 - 아이디는 이메이로) 예 claims.email
await this.$fbWriteSetDoc("members", user.claims.email, user.claims);
//store. 인증처리 결과르 확인을 위한 vue 프론트의 임의 변수에 저장 처리
await this.$store.dispatch('setClaims', user.claims);
}
//store에 레벨값이 들어올 때까지 기다린다.
const accessLevel=await this.$store.state.claims.accessLevel;
if(accessLevel){
this.$router.push("/");
}
},
async memberJoin(){
console.log("memberJoin 2 ");
if(!this.$refs.form.validate()) return this.$toasted.global.error('입력폼을 올바르게 작성해 주세요.');
const auth = this.$auth;
auth.languageCode = 'ko';
//1. Authentication 에회원 이메일 비밀번호 최초등록 (기타 정보는 업데이트 처리 되지않는다.) 및 로그인 처리된다.
//firebase functions 함수로 회원레벨 설정 함수가 등록되었을 시에 회원가입과 함께 회원레벨이 등록되어진다.
await this.$createUserWithEmailAndPassword(auth, this.form.email, this.form.password);
// 2. Authentication 에 이메일과 비밀번호 밖에 등록이 안되기 때문에 displayName 업데이트 및 photoURL 업데이트 처리한다.
await this.$updateProfile(this.$auth.currentUser, {
displayName: this.form.lastName + this.form.firstName , photoURL: ""
});
//3.현재 토큰 정보가져오기 - getIdTokenResult true 를해야 토큰값이 갱신된다.
const user= await auth.currentUser.getIdTokenResult(true);
//4.firebase store 또는 DB에 유저정보 확인
const confirmUser= await this.$fbGetData("members", user.claims.email);
if(confirmUser.data()==undefined){
//5. firebase store 또는 기타 mysql DB 등에 에 유저 정보 저장 - 아이디는 이메이로) 예 claims.email
await this.$fbWriteSetDoc("members", user.claims.email, user.claims);
//store. 인증처리 결과르 확인을 위한 vue 프론트의 임의 변수에 저장 처리
await this.$store.dispatch('setClaims', user.claims);
}
//6. 사용자에게 확인 메일 보내기 - firebase 에서 자동으로 이메일 전달 되며 메일 확인 후 클릭하면
//인증 처리 된다. ", "email_verified": false 가," true 변경 처리"
await sendEmailVerification(auth.currentUser);
//store에 레벨값이 들어올 때까지 기다린다.
const accessLevel=await this.$store.state.claims.accessLevel;
if(accessLevel){
this.$router.push("/");
}
}
}
}
</script>
<style scoped>
.recaptcha-terms-text{
font-size: 14px;
font-weight: 200;
color: #637282;
font-family: 'Noto Sans KR', sans-serif;
font-weight: 400;
}
</style>
3.sign.vue
<template>
<v-container grid-list-md class="mt-5">
<v-layout row wrap align-center justify-center class="mt-5">
<v-flex xs12 sm5 offset-sm1 class="hidden-xs-only mr-5 mt-5">
<v-img src="https://haatadmindashboard.azurewebsites.net/public/admin_css/assets/images/login-img.svg" ></v-img>
</v-flex>
<v-flex xs12 sm5 class="mt-5" >
<sign-in v-if="type"
@signInWithGoogle="signInWithGoogle" @signOut="signOut" @signInEmail="signInEmail"
:message="message" @type-change="typeChange"
></sign-in>
<sign-up v-else @type-change="typeChange" ></sign-up>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
//import store from "../store/index.js";
import SignIn from '@/components/auth/signIn';
import SignUp from '@/components/auth/signUp';
export default {
components:{
SignIn,
SignUp
},
data() {
return {
email: '',
password: '',
message: '',
type:true,
parentData:{
email: '',
password: '',
}
}
},
methods: {
// 구글 인증
async signInWithGoogle() {
const provider = this.$provider;
const auth = this.$auth;
auth.languageCode = 'ko';
//1.구글 인증 (인증과 동시에 firebase 의 Authentication 에 등록되어 있지않으면 등록처리된다.)
//등록시 fireabse functions 커스텀등록을 통해 에 유저 level 설정 할수 있다.
//참조 : https://firebase.google.com/docs/auth/admin/custom-claims?hl=ko
// 백엔드 서버 노드js function 개발 : exports.processSignUp = functions.auth.user().onCreate(async (user)
await this.$signInWithPopup(auth, provider);
//2.현재 토큰 정보가져오기 - getIdTokenResult true 를해야 토큰값이 갱신된다.
const user= await auth.currentUser.getIdTokenResult(true);
//3.firebase store 또는 DB에 유저정보 확인
const confirmUser= await this.$fbGetData("members", user.claims.email);
if(confirmUser.data()==undefined){
//confirmUser
//4. firebase store 또는 기타 mysql DB 등에 에 유저 정보 저장 - 아이디는 이메이로) 예 claims.email
await this.$fbWriteSetDoc("members", user.claims.email, user.claims);
//store. 인증처리 결과르 확인을 위한 vue 프론트의 임의 변수에 저장 처리
await this.$store.dispatch('setClaims', user.claims);
}
//store에 레벨값이 들어올 때까지 기다린다.
const accessLevel=await this.$store.state.claims.accessLevel;
if(accessLevel){
this.$router.push("/");
}
},
async signInEmail(email, password) {
try {
await this.$signInWithEmailAndPassword(this.$auth, email, password);
} catch (error) {
if(error.toString().indexOf('auth/wrong-password') !==-1){
this.$toasted.global.error("아이디 또는 비밀번호가 일치하지 않습니다.");
}else if(error.toString().indexOf('auth/user-not-found') !==-1){
this.$toasted.global.error("등록된 회원이 아닙니다.");
}else{
this.$toasted.global.error(error.toString());
}
}
},
async signOut() {
await this.$signOut(this.$auth);
//this.$router.go();
//this.$router.push("/");
},
typeChange(type){
console.log("type-change");
this.type=type;
},
}
}
</script>
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// const displayName = user.displayName;
// const email = user.email;
// const photoURL = user.photoURL;
// const emailVerified = user.emailVerified;
// const uid = user.uid;
export default new Vuex.Store({
state: {
title: '원래 제목',
user: null,
token: '',
loading: false,
claims: null,
firebaseLoaded: false,
dimLayer: true
},
mutations: {
setTitle(state, payload){
state.title = payload;
},
setUser(state, payload) {
state.firebaseLoaded = true;
state.user = payload;
},
setToken(state, token) {
state.token = token;
},
setClaims(state, claims) {
console.log(" 저장된 setClaims ");
// console.log(claims);
// console.log(" 종료 setClaims ");
state.claims = claims;
},
dimLayerOpen(state) {
console.log(" dimLayerOpen");
state.dimLayer = true;
},
dimLayerClose(state) {
state.dimLayer = false;
},
},
actions: {
getUser({commit}, user) {
commit('setUser', user);
if (!user) return;
return user.getIdToken()
.then(token => {
// console.log(" token");
console.log(token);
commit('setToken', token);
return user.getIdTokenResult();
})
.then(r => {
commit('setClaims', r.claims);
return r.claims;
})
},
setClaims({ commit }, claims) {
commit('setClaims', claims);
},
dimLayerOpen({ commit }) {
commit('dimLayerOpen');
},
dimLayerClose({ commit }) {
commit('dimLayerClose');
},
},
modules: {
}
})
소스 : https://github.com/braverokmc79/vf
소스 : https://github.com/braverokmc79/vf/commit/c01d4666b556c7c2198ef397a46ea8615ae0500c















댓글 ( 5)
댓글 남기기