In a Vue application I have many features that can only be used if the user is actively logged in.
The function that checks if the user is authenticated is like this:
import {useStore} from "vuex";
import {useRoute, useRouter} from "vue-router";
export default {
setup() {
const VueStore = useStore();
const VueRouter = useRouter();
const route$ = useRoute();
const isLoggedIn = ref(VueStore.state.securityStore.isLoggedIn);
async function authenticateIdentity() {
try {
await VueStore.dispatch('securityStore/autoLogin');
if (isLoggedIn !== true) {
return VueRouter.push({name: "Login", query: {redirect: route$.path}})
}
} catch (error) {
return VueRouter.push({name: "Login", query: {redirect: route$.path}})
}
}
}
}
The steps are simple:
- Ask the
VueStore
to run anaction
that logs in the user automatically (using cookies) - If the authentication passed do nothing (that is, let the calling function carry on)
- Else if not authenticated, take the user to the
Login
screen
I would like to keep this code in a separate file and use it in whichever component I need to. How can this be done in Vue3?
CodePudding user response:
You can create a plugin
const myAuthPlugin = {
install(app, options) {
// move the Authentication logic and method here
}
}
app.use(myAuthPlugin)
CodePudding user response:
It is possible to create a Vue3 composable that allows to reuse the function in other places.
The tricky part is the vue-router
. We have to make sure that the used router inside the composable is actually the same instance of the router as being used inside the App/components. We cannot use useRouter()
which is the method for using the router inside the setup function of components (in our composable we do not have a setup function). Therefore, we suggest to put the router definition in an extra module and share this module between App and composable definitions.
1. Create new file router.js
import {createRouter, createWebHashHistory} from 'vue-router'
const routes = [
{path: '/', name: 'Home', component: Home},
{path: '/login', name: 'Login', component: Login},
...
{path: "/:pathMatch(.*)*", component: NotFound},
]
const router = createRouter({
history: createWebHashHistory(),
routes: routes
})
export default router;
2. Use router module in main.js
import {createApp} from 'vue'
import router from './router.js'
import App from './components/App.vue'
const myApp = createApp(App);
myApp.use(router)
.mount('#app');
3. Create composable loggin.js
import {ref} from 'vue';
import store from './store.js'; // assuming this is the file containing the store definition
import router from './router.js';
export async function authenticateIdentity() {
const isLoggedIn = ref(store.state.securityStore.isLoggedIn);
try {
await store.dispatch('securityStore/autoLogin');
if (isLoggedIn !== true) {
return router.push({name: "Login", query: {redirect: router.currentRoute.path}})
}
} catch (error) {
return router.push({name: "Login", query: {redirect: router.currentRoute.path}})
}
}
4. Use composable in other components
<script>
import {authenticateIdentity} from 'loggin.js'
export default {
name: "LoginComponent",
methods: {
login(){
authenticateIdentity().then( ... ).catch( ... );
}
}
}
</script>
(adapt project structure / import paths / names)