Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncaught Error in onSnapshot: Error: Missing or insufficient permissions on signOut()

I'm using vuex and firebase to implement user authentication following the instruction of vuegram. I tried many ways to detach firebase listeners, the only one that stop warning error is the following:

var unsubscribe=fb.auth.onAuthStateChanged(user=>{
    if(user){
        store.commit('setCurrentUser',user)
        store.dispatch('fetchUserProfile')

        fb.usersCollection.doc(user.uid).onSnapshot(doc => {
            store.commit('setUserProfile', doc.data())
        })
    }
})
unsubscribe();

However, the code above just stop warning on signOut(), I can't update data anymore.

My store.js file:

var unsubscribe=fb.auth.onAuthStateChanged(user=>{
    if(user){
        store.commit('setCurrentUser',user)
        store.dispatch('fetchUserProfile')

        fb.usersCollection.doc(user.uid).onSnapshot(doc => {
            store.commit('setUserProfile', doc.data())
        })
    }
})

export const store=new Vuex.Store({
    state:{
        currentUser:null,
        userProfile:{}
    },
    actions:{
        clearData({commit}){
            commit('setCurrentUser',null)
            commit('setUserProfile', {})
        },
        fetchUserProfile({ commit, state }) {
             fb.usersCollection.doc(state.currentUser.uid).get().then(res => {
                commit('setUserProfile', res.data())

            }).catch(err => {
                console.log(err)
            })
        },
        updateProfile({ commit, state }, data) {
            let displayName = data.displayName

            fb.usersCollection.doc(state.currentUser.uid).set({
                displayName: displayName
            }, {merge:true}).then(function() {
                alert("Document successfully written!");
            })
            .catch(function(error) {
                alert("Error writing document: ", error);
            });
        }
    },
    mutations:{
        setCurrentUser(state, val) {
            state.currentUser = val
        },
        setUserProfile(state, val) {
            state.userProfile = val
        }
    }
})

The signOut method:

signOut: function(){
        fb.auth.signOut().then(()=> {
            this.$store.dispatch('clearData')
            this.$router.push('login')
        }).catch(function(error) {
            console.log(error);
        });
    }

My firebase rule:

allow read, write: if request.auth.uid!=null;
like image 444
JackJack Avatar asked Oct 16 '22 10:10

JackJack


2 Answers

Since you still have an active listener when you log out, the system detects that the client has lost permission to read that data and rejects the listener. This means you need to remove the listener before signing out to prevent the error message.

See the documentation on detaching listeners, you first get a reference to the unsubscribe function when you attach the listener:

unsubscribe = fb.usersCollection.doc(user.uid).onSnapshot(doc => {
    store.commit('setUserProfile', doc.data())
})

And then call that function before signing out:

signOut: function(){
    unsubscribe();
    fb.auth.signOut().then(()=> {
        this.$store.dispatch('clearData')
        this.$router.push('login')
    }).catch(function(error) {
        console.log(error);
    });
}
like image 60
Frank van Puffelen Avatar answered Nov 15 '22 08:11

Frank van Puffelen


If you have a logout button on many pages just navigate to a different page and call logout from there. Then you don't have to litter your code with unsubscribes.

like image 26
user1689987 Avatar answered Nov 15 '22 09:11

user1689987