Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS role based authentication with router

My use case is something like this.

  1. When someone login to the system, I identify user role at the login action and store that value as a state.
  2. I have 3 user roles, namely student,admin and dataEntry
  3. I have 3 separates routes for these 3 roles as well.(/student,/admin,/dataEntry)
  4. So, I want to route users to the system acroding to their user roles. Logically something like this.

if(userType == 'student'){
	router.push('/student')
},
if(userType == 'admin'){
	router.push('/admin')
}

How do I achieve this? I'm new to vueJS and I have no idea where to put these if conditions.

Here is my code Store.js

import Vue from 'vue';
import Vuex from 'Vuex';
import axios from 'axios';
import router from './main.js';

Vue.use(Vuex);

export const store = new Vuex.Store({
  state:{

    idToken:null,
    userId:null,
    userType:null,
    userName:null

  },

  mutations:{

    authUser(state,userData){

      state.idToken = userData.token,
      state.userId  = userData.id,
      state.userName = userData.userName,
      state.userType = userData.type

    },

    clearAuthData(state){

      state.idToken = null,
      state.userId = null,
      state.userName = null,
      state.userType = null

    }

},

  actions:{

    signup({commit},authData){
      axios.post('http://localhost/laravel_back/public/api/register', authData)
        .then(res => {
          commit('authUser',{
          token:res.data.idToken,
          userId:res.data.localId
          })
          //dispatch('storeUser',authData)
        })
        .catch(error => console.log("ERROR COMES FROM ACTION SIGN UP",error))
    },

    login({commit},authData){
      axios.post('http://localhost/laravel_back/public/api/login',authData

      )
        .then(res => {
          console.log("Back-end Response",res);

          commit('authUser',{
            token:res.data[0].token,
            userName:res.data[1][0].fname,
            id:res.data[2].id,
            type:res.data[3][0].role_id

        })})
        .catch(error => console.log(error))

        //router.push('/student')

      },
    


logout({commit}, {router}){
  commit('clearAuthData')
  router.replace('/')
},

  },
  getters:{
    userId(state){
      return state.userId

    },
    userType(state){
      return state.userType
    },
    userName(state){
      return state.userName
    },
    returnToken: state => {
      return state.idToken
    }

  }
});
header.vue

<template>
  <div class="fluid-container" id="headerr">
    <div class="container">
      <div class="row">
        <div class="col">
          <h1>Exams-portal</h1>
        </div>

        <div class="col form-group" v-if="!auth">
          <div class="row">
            <div class="col">
              <input type="email" name="email" value="" v-model="email" class="form-control float-right">
            </div>

            <div class="col" >
              <input type="password" name="password" value="" v-model="password" class="form-control float-right">
            </div>

            <div class="col">
              <button type="button" class="btn btn-primary " name="button" @click="onLogin">Login</button>
            </div>
          </div>
          <div class="row">
            <div class="col">
              <router-link :to="{ path:'findYourAccount' }">Forgot password?</router-link>
            </div>
          </div>
        </div>
        <div class="" v-if="auth" class="col-sm-6 form-group" >

          <div class="row">
            <div class="col">
              Logged as {{userName}}
              </div>

            <div class="col">
              <button type="button"  class="btn btn-primary float-right" name="button" @click="onLogout">Logout</button>
            </div>

          </div>


        </div>


      </div>
    </div>

  </div>
</template>
<script>
import { mapActions } from 'vuex';
  export default{
    data () {
      return {
        email: '',
        password: ''
      }
    },
    computed:{
      auth(){
        return this.$store.getters.isAuthenticated
      },
      userName(){
          return this.$store.getters.userName
        }

    },
    methods:{
      ...mapActions(["logout"]),
      onLogin () {

        const formData = {
          email: this.email,
          password: this.password,
          returnSecureToken:true
        }
        this.$store.dispatch('login',{
         email: this.email,
         password: this.password,
         //router: this.$router
       })

    },
    onLogout(){
      this.logout({ router: this.$router });
    }
    }
  }
</script>
<style scoped>
#headerr{
  color:white;
  background-color: #003459;
  padding: 10px;
}
</style>
like image 532
Pathum Kalhan Avatar asked Mar 20 '18 05:03

Pathum Kalhan


People also ask

Can you pass Props to router view Vue?

Vue Router 4 provides multiple ways of doing this: from setting the props property on the route record to true and automatically passing all params as props, setting the props property to a static object to provide static props, or setting it to a function that returns the desired props.

Does Vue have routing?

Vue router: Vue Router helps link between the browser's URL/History and Vue's components allowing for certain paths to render whatever view is associated with it. A vue router is used in building single-page applications (SPA). The vue-router can be set up by default while creating your new project.


1 Answers

I will say that you should handle this in the login action.

You identify the user role at the login action, then save the role as a state and redirect to the user page based on the user role, doing this in the same method/callback.

Other approach can be to have a the user role as a computed value in the login Vue component and handle the user role changes

computed: {
  userRole: function () {

    let role = this.$store.state.userRole
    if(role === 'student'){
      router.push('/student')
    } else if(role === 'admin'){
      router.push('/admin')
    }

    return role 
  }
}

but I think the first approach is better.

You don't have to pass the router (this.$router) to the store action. You can return a Promise from the login store action:

In Store.js:

login({commit},authData){
  return new Promise(resolve => {
    axios.post('http://localhost/laravel_back/public/api/login',authData)
    .then(res => {
      console.log("Back-end Response",res);
      commit('authUser',{
        token:res.data[0].token,
        userName:res.data[1][0].fname,
        id:res.data[2].id,
        type:res.data[3][0].role_id
      })
      //get the role
      let role = res.data[3][0].role_id
      resolve(role);
    }).catch(error => console.log(error))
  })
}

In component:

onLogin () {
  this.$store.dispatch('login', {
    email: this.email,
    password: this.password
  }).then(role => {
    this.$router.push('/'+role)
  });
}
like image 118
Jorj Avatar answered Sep 29 '22 14:09

Jorj