Vue firebase: Cannot retrieve user data. Undefined - javascript

I want to retrieve user profile data to show the information in user profile page.
In the realtime database, I could insert the data as the picture below.
But some information such as address, business, city, phone and post, those information is undefined, so I cannot retrieve the data.
And this is the dev tool network tab.
I am using vuex, and this is my code, store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import fireApp from '#/plugins/firebase'
//import 'firebase/firebase-auth'
Vue.use(Vuex)
export default new Vuex.Store({
namespaced: true,
state: {
user: null,
error: null,
busy: false,
jobDone: false
},
mutations: {
setUser (state, payload) {
state.user = payload
},
setError (state, payload) {
state.error = payload
},
clearError (state) {
state.error = null
},
setBusy (state, payload) {
state.busy = payload
},
setJobDone (state, payload) {
state.jobDone = payload
},
},
actions: {
loginUser({commit}, payload) {
commit('setBusy', true)
commit('clearError')
//1.login user
//2.Find group user logins
//3.set logged in user
let LoggedinUser = null;
fireApp.auth().signInWithEmailAndPassword(payload.email, payload.password)
.then(userCredential => {
LoggedinUser = userCredential.user;
var user = fireApp.auth().currentUser;
const authUser = {
id: user.uid,
contact: user.displayName,
business: user.business,
email: user.email,
phone: user.phone,
address: user.address,
post: user.post,
city: user.city,
}
return fireApp.database().ref('groups').orderByChild('name').equalTo('Pro').once('value')
.then(snapShot => {
const groupKey = Object.keys(snapShot.val())[0]
return fireApp.database().ref(`userGroups/${groupKey}`).child(`${authUser.id}`).once('value')
.then(ugroupSnap => {
if (ugroupSnap.exists()) {
authUser.role = 'pro'
}
console.log('USER', authUser)
commit('setUser', authUser)
commit('setBusy', false)
commit('setJobDone', true)
})
})
})
.catch(error => {
console.log(error)
commit('setBusy', false)
commit('setError', error)
})
},
},
getters: {
user (state) {
return state.user
},
loginStatusPro (state) {
return state.user !== null && state.user !== undefined
},
userRole (state) {
const isLoggedIn = state.user !== null && state.user !== undefined
return(isLoggedIn) ? state.user.role : 'Pro'
},
error (state) {
return state.error
},
busy (state) {
return state.busy
},
jobDone (state) {
return state.jobDone
}
},
modules: {
}
})
This is user profile page. Profile.vue
<script>
import ErrorBar from '#/components/ErrorBar'
import apiJobMixin from '#/mixins/apiJobMixin'
export default {
data() {
return {
//contact: "",
business: "",
address: "",
post: "",
city: "",
}
},
mixins: [apiJobMixin],
components: {
ErrorBar: ErrorBar
},
created () {
this.$store.commit('clearError')
const user = this.$store.getters.user
if (user) {
//this.contact = user.contact
this.business = user.business
this.address = user.address
this.post = user.post
this.city = user.city
}
},
computed: {
userData () {
return this.$store.getters.user
}
},
watch: {
userData (value) {
if (value) {
//this.contact = value.contact
this.business = value.business
this.address = value.address
this.post = value.post
this.city = value.city
}
}
}
}
</script>
I hope you can help me out.

Related

Wrong authentication with Firebase

I have added authorization to my Nuxt app, but something is wrong. When i enter wrong password or email, I am still redirected to the main page of the application, although I have to stay on the authorization page and try to log in again.
Here is my code:
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut
} from 'firebase/auth'
export default {
data() {
return {
snackBar: false,
snackBarText: 'No Error Message',
auth: {
email: '',
password: ''
}
}
},
methods: {
login() {
let that = this
this.$fire.auth.signInWithEmailAndPassword(this.auth.email, this.auth.password)
.catch(function (error) {
console.log(error.message);
that.snackBarText = error.message
that.snackBar = true
// $nuxt.$router.push('/login')
}).then((user) => {
console.log(user);
$nuxt.$router.push('/')
})
}
}
}
middleware:
export default function ({ app, route, redirect }) {
if (route.path !== '/login') {
// we are on the protected route
if (!app.$fire.auth.currentUser) {
// take them to sign in in a page
return redirect('/login')
}
} else if (route.path === '/login') {
if (!app.$fire.auth.currentUser) {
// leave them on the sign in page
} else {
return redirect('/')
}
}
}
store:
const state = () => ({
user: null,
};
const mutations = {
SET_USER(state, user) {
state.user = user
},
}
const actions = {
async onAuthStateChangedAction(context, { authUser, claims }) {
if (!authUser) {
context.commit('SET_USER', null)
this.$router.push({
path: '/login'
})
} else {
const { uid, email } = authUser;
context.commit('SET_USER', {
uid,
email
})
}
}
}
const getters = {
getUser(state) {
return state.user
}
}
export default {
state,
actions,
mutations,
getters,
}
Form for authorization is in component popup, which is sent to page login.vue

Nuxt middleware to check if user is logged in not working

I am trying to check if a user is authenticated and redirect them depending on the page they are in. for example if the user is logged in and they try to visit the login or signup page, they should be redirected. I have a middleware for that.
when I log in the user, the authenticateUser action runs and the user is created, when I check my cookies and local storage on the browser, I see that it is set correctly, but when I visit the login page after logging in, it doesn't redirect me.
middleware/altauth.js
export default function (context) {
console.log(context.store.getters('profile/isAuthenticated'))
if (context.store.getters.isAuthenticated) {
context.redirect('/')
}
}
also the token is both saved using Cookies and local storage and is persistence is through this middleware
middleware/checkauth.js
export default function (context) {
if(context.hasOwnProperty('ssrContext')) {
context.store.dispatch('profile/initAuth', context.ssrContext.req);
} else {
context.store.dispatch('profile/initAuth', null);
}
}
and below are the values for my store
import Cookie from 'js-cookie';
export const state = () => ({
token: null,
})
export const mutations = {
setToken(state, token) {
state.token = token
},
clearToken(state) {
state.token = null
}
}
export const actions = {
async authenticateUser(vuexContext, authData) {
let authUrl = 'https://look.herokuapp.com/signup/'
if (authData.isLogin) {
authUrl = 'https://look.herokuapp.com/login/'
}
return this.$axios
.$post(authUrl, authData.form)
.then(data => {
console.log(data);
const token = data.token
vuexContext.commit('setToken', token)
localStorage.setItem("token", token)
Cookie.set('jwt', token);
})
.catch(e => console.log(e))
},
initAuth(vuexContext, req) {
let token
if (req) {
if (!req.headers.cookie) {
return;
}
const jwtCookie = req.headers.cookie
.split(';')
.find(c => c.trim().startsWith('jwt='));
if (!jwtCookie) {
return;
}
token = jwtCookie.split('=')[1];
} else {
token = localStorage.getItem('token');
if (!token) {
return;
}
}
vuexContext.commit('setToken', token);
}
}
export const getters = {
isAuthenticated(state) {
return state.token != null;
},
}
please help, i don't know what the problem can be
Here is a basic but full example for auth system in SSR nuxt
You will need two apis for this, one will return token info with user info, and the other will return user info only.
for example
POST http://example.com/api/auth/authorizations
{
token: 'abcdefghijklmn',
expired_at: 12345678,
user: {
name: 'Tom',
is_admin: true
}
}
// this need authed
GET http://example.com/api/auth/user
{
name: 'Tom',
is_admin: true
}
nuxt.config.js
plugins:[
'~plugins/axios',
],
buildModules: [
'#nuxtjs/axios',
],
router: {
middleware: [
'check-auth'
]
},
./pages/login.vue
<template>
<form #submit.prevent="login">
<input type="text" name="username" v-model="form.username">
<input type="password" name="password" v-model="form.password">
</form>
</template>
<script type="text/javascript">
export default{
data(){
return {
form: {username: '', password: ''}
}
},
methods: {
login(){
this.$axios.post(`/auth/authorizations`, this.form)
.then(({ data }) => {
let { user, token } = data;
this.$store.commit('auth/setToken', token);
this.$store.commit('auth/updateUser', user);
this.$router.push('/');
})
}
}
}
</script>
store/index.js
const cookieFromRequest = (request, key) => {
if (!request.headers.cookie) {
return;
}
const cookie = request.headers.cookie.split(';').find(
c => c.trim().startsWith(`${key}=`)
);
if (cookie) {
return cookie.split('=')[1];
}
}
export const actions = {
nuxtServerInit({ commit, dispatch, route }, { req }){
const token = cookieFromRequest(req, 'token');
if (!!token) {
commit('auth/setToken', token);
}
}
};
middleware/check-auth.js
export default async ({ $axios, store }) => {
const token = store.getters['auth/token'];
if (process.server) {
if (token) {
$axios.defaults.headers.common.Authorization = `Bearer ${token}`;
} else {
delete $axios.defaults.headers.common.Authorization;
}
}
if (!store.getters['auth/check'] && token) {
await store.dispatch('auth/fetchUser');
}
}
store/auth.js
import Cookie from 'js-cookie';
export const state = () => ({
user: null,
token: null
});
export const getters = {
user: state => state.user,
token: state => state.token,
check: state => state.user !== null
};
export const mutations = {
setToken(state, token){
state.token = token;
},
fetchUserSuccess(state, user){
state.user = user;
},
fetchUserFailure(state){
state.user = null;
},
logout(state){
state.token = null;
state.user = null;
},
updateUser(state, { user }){
state.user = user;
}
}
export const actions = {
saveToken({ commit }, { token, remember }){
commit('setToken', token);
Cookie.set('token', token);
},
async fetchUser({ commit }){
try{
const { data } = await this.$axios.get('/auth/user');
commit('fetchUserSuccess', data);
}catch(e){
Cookie.remove('token');
commit('fetchUserFailure');
}
},
updateUser({ commit }, payload){
commit('updateUser', payload);
},
async logout({ commit }){
try{
await this.$axios.delete('/auth/authorizations');
}catch(e){}
Cookie.remove('token');
commit('logout');
}
}
plugins/axios.js
export default ({ $axios, store }) => {
$axios.setBaseURL('http://example.com/api');
const token = store.getters['auth/token'];
if (token) {
$axios.setToken(token, 'Bearer')
}
$axios.onResponseError(error => {
const { status } = error.response || {};
if (status === 401 && store.getters['auth/check']) {
store.commit('auth/logout');
}
else{
return Promise.reject(error);
}
});
}
Then you can do what you want in your middleware, such as check auth
middleware/auth.js
export default function ({ store, redirect }){
if (!store.getters['auth/check']) {
return redirect(`/login`);
}
}

How to check if mail already exists in database when using updateProfile () function

I do not know how to implement a method in which when using the updateProfile () function, it checks the firestore if such mail already exists and then an error would pop up. I did a test method in MyAccount.vue, but it doesn't work, if I don't type anything and click, nothing updates, but that's not the point, I would like it to check if such mail exists.
./src/views/MyAccount.vue
import { mapState } from 'vuex';
export default {
data() {
return {
user: {
username: '',
email: '',
password: ''
}
};
},
computed: {
...mapState(['userProfile']),
},
methods: {
updateProfile() {
this.$store.dispatch('updateProfile', {
username:
this.user.username !== ''
? this.user.username
: this.userProfile.username,
email:
this.user.email !== ''
? this.user.email
: this.userProfile.email,
password:
this.user.password !== ''
? this.user.password
: this.userProfile.password
});
this.user.username = '';
this.user.email = '';
this.user.password = '';
this.showSuccess = true;
setTimeout(() => {
this.showSuccess = false;
}, 2000);
}
}
};
</script>
./src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import * as fb from '../firebase';
import router from '../router/index';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
userProfile: {},
notes: []
},
mutations: {
setUserProfile(state, val) {
state.userProfile = val;
},
setNotes(state, val) {
state.notes = val;
}
},
actions: {
async updateProfile({ commit, dispatch }, user) {
const userId = fb.auth.currentUser.uid;
await fb.usersCollection.doc(userId).update({
username: user.username,
email: user.email,
password: user.password
});
dispatch('fetchUserProfile', { uid: userId });
},
async fetchUserProfile({ commit }, user) {
// fetch user profile
const userProfile = await fb.usersCollection.doc(user.uid).get();
// set user profile in state
commit('setUserProfile', userProfile.data());
// change router to dashboard
if (router.currentRoute.path === '/login') {
router.push('/');
}
}
},
modules: {}
});
export default store;
Before updating, try this:
const current = await fb.usersCollection.where('email', '==', user.email).get()
if (current.empty === true) {
// You are free to do the update, because the email is not in use already
}
Of course, this works best if you make sure to alway lowercase your emails before querying or storing them in the database

Vuex and firebase: The user id is undefined in the firebase database

I am creating an e-commerce web site.
Now I finished creating the new account with email and password.
And I want to insert the user email, full name, and timestamp in the database.
As you can see in the picture below, I could see the USER data in the google chrome dev console.
But when I checked the firebase database in the browser, I cannot see the user id. And instead, I see undefined in the user id column.
Now I am on the step3 process.
Add user data into database
I cannot figure out why it's happening, so I hope you can help me out.
This is my store/index.js file.
import fireApp from '#/plugins/firebase'
export const state = () => ({
user: null,
error: null,
busy: false,
jobDone: false
})
export const mutations = {
setUser (state, payload) {
state.user = payload
},
setError (state, payload) {
state.error = payload
},
clearError (state, payload) {
state.error = null
},
setBusy (state, payload) {
state.busy = payload
},
setJobDone (state, payload) {
state.jobDone = payload
},
}
export const actions = {
signUpUser({commit}, payload) {
commit('setBusy', true)
commit('clearError')
//1.Signup new user.
//2.Update firebase user profile & set local user data.
//3.Add user data into database
//4.Attach user to consumer group
let newUser = null
fireApp.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(user => {
newUser = user
var user = fireApp.auth().currentUser;
user.updateProfile({ displayName: payload.fullname })
const currentUser = {
id: user.uid,
email: payload.email,
name: payload.fullname,
role: 'consumer'
}
console.log('USER', currentUser)
commit('setUser', currentUser)
})
.then(() => {
const userData = {
email: payload.email,
fullname: payload.fullname,
createdAt: new Date().toISOString()
}
fireApp.database().ref(`users/${newUser.uid}`).set(userData)
})
.then(() => {
commit('setJobDone', true)
commit('setBusy', false)
})
.catch(error => {
commit('setBusy', false)
commit('setError', error)
})
}
}
export const getters = {
user (state) {
return state.user
},
error (state) {
return state.error
},
busy (state) {
return state.busy
},
jobDone (state) {
return state.jobDone
}
}
This is because the promise returned by createUserWithEmailAndPassword() method resolves with an UserCredential object and not with a User one.
You should use the user property of the UserCredential, as follows:
let newUser = null
fireApp.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(userCredential => {
newUser = userCredential.user;
//...
Note also that you don't need to call fireApp.auth().currentUser to get the user.
When using the createUserWithEmailAndPassword() method, on successful creation of the user account, this user will also be signed in to your application, so just get the user with userCredential.user, as explained above.
In addition, note that the updateProfile() method is asynchronous and returns a Promise, which you need to include in your promises chain.
So the following should do the trick (untested):
signUpUser({commit}, payload) {
commit('setBusy', true)
commit('clearError')
//1.Signup new user.
//2.Update firebase user profile & set local user data.
//3.Add user data into database
//4.Attach user to consumer group
let user = null;
fireApp.auth().createUserWithEmailAndPassword(payload.email, payload.password)
.then(userCredential => {
user = userCredential.user;
return user.updateProfile({ displayName: payload.fullname });
})
.then(() => {
const currentUser = {
id: user.uid,
email: payload.email,
name: payload.fullname,
role: 'consumer'
}
console.log('USER', currentUser)
commit('setUser', currentUser)
const userData = {
email: payload.email,
fullname: payload.fullname,
createdAt: new Date().toISOString()
}
return fireApp.database().ref(`users/${user.uid}`).set(userData)
})
.then(() => {
commit('setJobDone', true)
commit('setBusy', false)
})
.catch(error => {
commit('setBusy', false)
commit('setError', error)
})
}

react relay login mutation not updating viewer

i'm trying to add authentication to my app using jwt token. I've created a LoginMutation with the FIELDS_CHANGE type but it looks like relay doesn't hook it up with the existing model.
I've listed my relay mutation and schema mutation.
My LoginMutation:
import Relay from 'react-relay';
export default class LoginMutation extends Relay.Mutation {
static fragments = {
viewer: () => Relay.QL`
fragment on User {
id
}
`
};
getMutation() {
return Relay.QL`mutation{loginUser}`;
}
getFatQuery() {
return Relay.QL`
fragment on LoginPayload {
viewer {
userId
email
password
jwt_token
}
}
`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
viewer: this.props.viewer.id
}
}];
}
getVariables() {
// inputs to the mutation
return {
email: this.props.credentials.email,
password: this.props.credentials.password
};
}
getOptimisticResponse() {
return {
viewer: {
email: this.props.credentials.email
}
};
}
}
const loginMutation = mutationWithClientMutationId({
name: 'Login',
inputFields: {
email: {
type: new GraphQLNonNull(GraphQLString)
},
password: {
type: new GraphQLNonNull(GraphQLString)
}
},
outputFields: {
viewer: {
type: userType,
resolve: (user) => user
}
},
mutateAndGetPayload: ({ email, password }, request) => {
return getUserByCredentials(email, password)
.then((user) => {
if (!user) {
return newUser;
}
user.jwt_token = jwt.sign({
id: user.id,
name: user.name,
email: user.email
}, JWT_SECRET);
return user;
})
.catch((error) => { throw error; });
}
});

Categories

Resources