Store user in vuex after login - vue.js

I am trying to create login page. SO for this, I am making a call. After I get the response, I am storing cookie and with the cookie I am getting the user info. What I am trying to do is store this user info in Vuex store. Here is whole of my logic for this:
export default {
name: 'Login',
mounted() {
EventBus.$on(GENERAL_APP_CONSTANTS.Events.CheckAuthentication, () => {
this.authenticated = authHelper.validAuthentication();
if (this.authenticated) {
this.email = this.password = "";
this.authenticationFailed = false;
}
});
EventBus.$on(GENERAL_APP_CONSTANTS.Events.LoginFailed, () => {
this.authenticationFailed = true
});
},
data () {
return {
authenticated: false,
authenticationFailed: false,
email: '',
password: '',
rememberMe: false,
cookieName: "_token",
cookie: "",
cookieValue: "",
}
},
validations: {
email: {
required,
email,
},
password: {
required,
minLength: minLength(0)
},
},
methods: {
signIn: function () {
authHelper.signIn(this.email, this.password, () => {
this.$router.push({name: 'home'});
});
this.cookie = cookieHelper.getCookie(this.cookieName);
this.cookieValue = cookieHelper.getCookieValue(this.cookie);
this.storeUser();
},
storeUser: function () {
apiHelper.getRequest(
`/users/${cookieHelper.parseJwt(this.cookie).user_id}`,
(response) => {
this.$store.dispatch('storeUser', {
user: response.data,
})
}
)
},
}
}
So, as you see below, my user in Vuex store is still empty:
my mutation is:
export const STORE_USER = (state, {user}) => {
state.user = user;
}
my action is:
export const storeUser = ({commit}, {user}) => {
commit('STORE_USER', {user});
}
Could you have a look and let me know, where do you think I am making something wrong.

Related

How to store user info after login in Vuex

I am trying to make an api call in login and I want to store it in Vuex store. So in the beginning my mutation:
export const STORE_USER = (state, {user}) => {
state.user = user;
}
and my action:
export const storeUser = ({commit}, {user}) => {
commit('STORE_USER', {user});
}
So as you see after login, I want to make an api call and get the user information. I want to this user information in Vuex store but it comes empty.
So I am expecting the state that you see above should be filled after login. My login component is:
export default {
name: 'Login',
mounted() {
EventBus.$on(GENERAL_APP_CONSTANTS.Events.CheckAuthentication, () => {
this.authenticated = authHelper.validAuthentication();
this.cookie = cookieHelper.getCookie(this.cookieName);
this.cookieValue = cookieHelper.getCookieValue(this.cookie);
if (this.authenticated) {
this.email = this.password = "";
this.authenticationFailed = false;
this.storeUser();
}
});
EventBus.$on(GENERAL_APP_CONSTANTS.Events.LoginFailed, () => {
this.authenticationFailed = true
});
},
data () {
return {
authenticated: false,
authenticationFailed: false,
email: '',
password: '',
rememberMe: false,
cookieName: "_token",
cookie: "",
cookieValue: "",
}
},
methods: {
signIn: function () {
authHelper.signIn(this.email, this.password, () => {
this.$router.push({name: 'home'});
});
},
storeUser: function () {
apiHelper.getRequest(
`/users/${cookieHelper.parseJwt(this.cookieValue).user_id}`,
(response) => {
this.$store.dispatch('storeUser', {
user: response.data,
})
}
)
},
}
}
So why do you think the in-store user Object is empty? Because I response.data is not empty either. Please let me know.

Unknown action type in Nuxt Vuex store

I have a problem calling the action from vuex. Everytime I try to access the loginUser action I get an error 'unknown action type' from vuex. maybe I'm not calling it the right way. Please tell me what's wrong with my code.
store: user.js
import axios from 'axios'
export const state = () => ({
users: [],
loggedIn: false,
})
export const getters = {
getLoggedIn: (state) => { return state.loggedIn },
}
export const actions = {
loginUser({ commit }, payload){
if(state.loggedIn){
console.log("you're already logged in!")
}else{
return new Promise(async(resolve, reject) => {
const { data } = await axios.post('/api/users/login-admin', {
login: payload.login,
password: payload.password
})
if(data.success){
commit("loggedIn", true)
resolve()
}else{
commit("loggedIn", false)
reject('an error has ocurred')
}
return data.success
}).catch(err => alert(errCodes(err.code)))
}
},
}
export const mutations = {
setLoggedIn(state, payload) {
state.loggedIn = payload
}
}
login.vue
computed: {
...mapGetters(['getCount'] , {user: 'getLoggedIn'}),
...mapActions([
'loginUser'
]),
},
methods: {
onSubmit: function(){
this.$store.dispatch({
type: 'loginUser',
email: this.login,
pass: this.pass
}).then(()=>{
this.$router.push('../admin_2065')
this.onReset()
}).catch(e => console.log(e))
},
onReset(){
this.login = ''
this.pass = ''
this.$nextTick().then(() => {
this.ready = true
})
}
},
error:
any help will be appreciated, thanks.
mapActions should be inside the methods option and add the namespace user/ :
computed: {
...mapGetters(['getCount'] , {user: 'getLoggedIn'}),
},
methods: {
...mapActions([
'user/loginUser'
]),
onSubmit: function(){
this['user/loginUser']({
email: this.login,
pass: this.pass
}).then(()=>{
this.$router.push('../admin_2065')
this.onReset()
}).catch(e => console.log(e))
},
onReset(){
this.login = ''
this.pass = ''
this.$nextTick().then(() => {
this.ready = true
})
}
},

loggedIn state reverts back to false after Logging in and doesn't allow me to guard route

I'm trying to guard my routes with state: { loggedIn: false }, when I login from my Login.vue component the goal is to trigger an action this.$store.dispatch('setLogin') that mutates the state of loggedIn to true. There is then navigation guard that is suppose to prevent me form seeing my Login.vue and Regester.vue components. The problem is that it seems like the state changes to true, but not the base state: allowing me to keep hitting the /auth/login and /auth/register routes.
Routes
const routes = [
{
path: '/auth',
name: 'auth',
component: Auth,
children: [
{ name: 'login', path: 'login', component: Login },
{ name: 'register', path: 'register', component: Register },
],
meta: {
requiresVisitor: true,
}
},
{
path: '/logout',
name: 'logout',
component: Logout
}
]
Login Component
login() {
this.$http.get('/sanctum/csrf-cookie').then(response => {
this.$http.post('/login', {
email: this.username,
password: this.password,
}).then(response2 => {
this.$store.dispatch('setLogin')
this.$store.dispatch('getUser')
alert(this.$store.state.loggedIn)
this.$router.push({ name: 'Home' })
}).catch(error => {
console.log(error.response.data);
const key = Object.keys(error.response.data.errors)[0]
this.errorMessage = error.response.data.errors[key][0]
})
});
}
Vuex
export default new Vuex.Store({
state: {
loggedIn: false,
user: JSON.parse(localStorage.getItem('user')) || null,
},
mutations: {
setLogin: (state) => {
state.loggedIn = true
},
SET_USER_DATA (state, userData) {
localStorage.setItem('user', JSON.stringify(userData))
state.user = userData;
},
removeUser(state) {
localStorage.removeItem('user');
state.user = null;
}
},
actions: {
getUser(context) {
if (context.state.loggedIn) {
alert('hit');
return new Promise((resolve, reject) => {
axios.get('api/user')
.then(response => {
context.commit('SET_USER_DATA', response.data.data)
resolve(response)
})
.catch(error => {
reject(error)
})
})
}
},
setLogin(context){
context.commit('setLogin')
}
},
modules: {
}
})
It's strange because alert(this.$store.state.loggedIn) renders true, but when I go back the auth link there's a mounted state alert that comes back false.
Here's my navigation guards as well:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!store.state.loggedIn) {
next({
name: 'login',
})
} else {
next()
}
} else if (to.matched.some(record => record.meta.requiresVisitor)) {
if (store.state.loggedIn) {
next({
name: 'Home',
})
return
} else {
next()
}
} else {
next()
}
})
You need to store the loggedIn user in local storage:
setLogin: (state) => {
state.loggedIn = localStorage.setItem('loggedIn', 'true')
state.loggedIn = true
},
Then your state should look like:
state: {
loggedIn: localStorage.getItem('loggedIn') || null,
},

Access Vue app (this) from non vue file

I'm new to vue (started using vue 2) I'm using Store (vuex) and I'm trying to acheive something.
basically I managed to install the vue-auth plugin : I have this.$auth that I can call from within .vue files.
Now using the store I wanna call the userLogin function by dispatching the call like this from a vue file :
<script>
export default {
computed: {
comparePasswords() {
return this.password === this.passwordConfirm
? true
: "Passwords don't match";
}
},
methods: {
userSignUp() {
if (this.comparePasswords !== true) {
return;
}
this.$store.dispatch("userSignUp", {
email: this.email,
password: this.password
});
}
},
data() {
return {
email: "",
password: "",
passwordConfirm: ""
};
}
};
</script>
in the store/index I'm trying to access the 'this.$auth' I do understand is some kind of context switching but I don't know how to access the vue app instance. :
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let app = this
export const store = new Vuex.Store({
state: {
appTitle: 'LiveScale Dashboard',
user: null,
error: null,
loading: false
},
mutations: {
setUser(state, payload) {
state.user = payload
},
setError(state, payload) {
state.error = payload
},
setLoading(state, payload) {
state.loading = payload
}
},
actions: {
userLogin({ commit }, payload) {
commit('setLoading', true)
var redirect = this.$auth.redirect(); // THIS IS WRONG.
this.$auth.login({ // THIS IS WRONG.
body: payload, // Vue-resource
data: payload, // Axios
rememberMe: this.data.rememberMe,
redirect: { name: redirect ? redirect.from.name : 'account' },
fetchUser: this.data.fetchUser
})
.then(() => {
commit('setUser', this.context)
commit('setLoading', false)
router.push('/home')
}, (res) => {
console.log('error ' + this.context);
commit('setError', res.data)
commit('setLoading', false)
});
},
userSignUp({ commit }, payload) {
// ...
}
},
getters: {}
})
Thanks for your help
try using Vue.$auth in index.js it should work
The idea (so far) is to pass the instance as an argument to the function as follows :
this.$store.dispatch("userSignUp", {
email: this.email,
password: this.password,
auth: this.$auth //added this line
});
and then in the store -> actions , payload.auth will contain my auth plugin :
userLogin({ commit }, payload) {
commit('setLoading', true)
var redirect = payload.auth.redirect();
payload.auth.login({
body: payload, // Vue-resource
data: payload, // Axios
rememberMe: this.data.rememberMe,
redirect: { name: redirect ? redirect.from.name : 'account' },
fetchUser: this.data.fetchUser
})
.then(() => {
commit('setUser', this.context)
commit('setLoading', false)
router.push('/home')
}, (res) => {
console.log('error ' + this.context);
commit('setError', res.data)
commit('setLoading', false)
});
},
I don't know if it's the best practice or not, but this is how I managed to do it. Please feel free to suggest anything.

Nuxt Auth Module Authenticated User Data

I have an API api/auth that is used to log users in. It expects to receive an access_token (as URL query, from Headers, or from request body), a username, and a password. I've been using the Vue Chrome Developer Tool and even though I get a 201 response from the server, the auth.loggedIn state is still false. I think that might be the reason why my redirect paths on the nuxt.config.js isn't working as well. Can anyone point me to the right direction on why it doesn't work?
This is a screenshot of the Vue Chrome Developer Tool
This is the JSON response of the server after logging in. The token here is different from the access_token as noted above.
{
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"user": {
"user_name": "xxxxxxxxxxxxxxxxxx",
"uid": "xxxxxxxxxxxxxxxxxx",
"user_data": "XXXXXXXXXXXXXXXXXXXXXXXXX"
}
}
Here is the relevant part of nuxt.config.js
export default {
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth',
['bootstrap-vue/nuxt', { css: false }]
],
router: {
middleware: [ 'auth' ]
},
auth: {
strategies: {
local: {
endpoints: {
login: {
url: '/api/auth?access_token=XXXXXXXXXXXXXXXXXXXXXX',
method: 'post',
propertyName: 'token'
},
logout: {
url: '/api/auth/logout',
method: 'post'
},
user: {
url: '/api/users/me',
method: 'get',
propertyName: 'user'
}
}
}
},
redirect: {
login: '/',
logout: '/',
home: '/home'
},
token: {
name: 'token'
},
cookie: {
name: 'token'
},
rewriteRedirects: true
},
axios: {
baseURL: 'http://localhost:9000/'
}
}
And my store/index.js
export const state = () => ({
authUser: null
})
export const mutations = {
SET_USER: function (state, user) {
state.authUser = user
}
}
export const actions = {
nuxtServerInit ({ commit }, { req }) {
if (req.session && req.user) {
commit('SET_USER', req.user)
}
},
async login ({ commit }, { username, password }) {
const auth = {
username: username,
password: password
}
try {
const { user } = this.$auth.loginWith('local', { auth })
commit('SET_USER', user)
} catch (err) {
console.error(err)
}
}
}
The login action in the store is triggered by this method in the page:
export default {
auth: false,
methods: {
async login () {
try {
await this.$store.dispatch('login', {
username: this.form.email,
password: this.form.password
})
} catch (err) {
this.alert.status = true
this.alert.type = 'danger'
this.alert.response = err
}
}
}
}
P.S. I realize I'm explicitly including the access_token in the URL. Currently, I don't know where a master_key or the like can be set in the Nuxt Auth Module.
Try this in your store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = () => new Vuex.Store({
state: {
authUser: null
},
mutations: {
SET_USER: function (state, user) {
state.authUser = user
}
},
actions: {
CHECK_AUTH: function(token, router) {
if (token === null) {
router.push('/login')
}
}
}
})
export default store
And for the router, this should work globally:
$nuxt._router.push('/')