Vue Router Navigation Guard Dynamic Import - javascript

I want to dynamically import data from component file to router file and allow next() depending upon value of imported data.
in App.vue I'm triggering this.$router.push({name: "Dashboard"}) when data authenticated: false changes to true. I'm triggering it with watch.
Problem is, router file will always receive original value false even with dynamic importing.
App.vue
watch: {
authenticated(){
console.log(this.authenticated) //Outputs 'true'
this.$router.push({name: 'Dashboard'}); //Triggers routing
}
}
router file (index.js)
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
beforeEnter(to, from, next){
(async ()=>{
const mod = await import('../view/App.vue'); //Dynamic import
let result = mod.default.data().auth; //Access 'authenticated' value from App.vue
console.log(result); //Output is 'false', but it should be 'true'
result ? next() : next({name: 'Login'});
})()
}
}
I tried many different async methods as well but nothing worked.

Use In-Component Guard in your App.vue as specified here and remove the authentication login from router file:
beforeRouteLeave(to, from, next) {
if (to.name === 'Dashboard' && this.authenticated) {
next();
}
else {
next({ name: 'Login' });
}
}

Related

Vue Router access route only from certain page

After a user has logged in the first time I redirect him to the page CreateProfile where he types in all the profile information. Afterwards I want to make this site not accessible anymore, such as if the user types the URL into the browser (e.g. www.myproject.com/createProfile).
How can I make sure that only the redirection from my login page has access to the CreateProfile page? That is, if the user types in the URL manually he will be redirected e.g. to the 404 page.
Currently my route for CreateProfile looks the following:
{
path: '/createprofile',
name: 'CreateProfile',
component: CreateProfile,
beforeEnter: (to, from, next) => {
if (store.getters.getUserStatus == true) {
next()
} else {
next({ name: 'Login' })
}
}
}
Thanks!!
You can check the from route object in the beforeEnter navigation guard to test the previous route location.
For example, check that the from.name property is Login, which will only be true when there has been the redirect you want. (Assuming you don't also provide a <router-link> from Login):
beforeEnter: (to, from, next) => {
const isRedirected = from.name === 'Login';
if (isRedirected && store.getters.getUserStatus == true) {
next()
} else {
next({ name: 'Login' })
}
}

nuxt router.js automatically updates how to prevent this?

I have a nuxt project. And located in the .nuxt file there is a router.js file when i want to add my own code to it like this:
routes: [{
path: "/ingelogd",
component: _0716b7e1,
name: "ingelogd",
meta: {requiresAuth: true}
}]
router.beforeEach((to, from, next)=> {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const isAuthenticated = firebase.auth().currentUser;
if(requiresAuth && !isAuthenticated) {
next("/reserveren")
} else {
next()
}
})
it automatically updates the code to this:
routes: [{
path: "/ingelogd",
component: _0716b7e1,
name: "ingelogd",
}]
Is there someone who knows what the problem is please let me know.
You shouldn't edit any file in your .nuxt directory, here is the docs about it.
You should use router middlewares to execute this kind of logic, take a look!
You should not modify any file in the .nuxt directory. In this situation you should work with middleware,
in middleware folder in the project root add file named auth.js with a content like :
export default function ({ app,route }) {
app.router.beforeEach((to, from, next)=> {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const isAuthenticated = firebase.auth().currentUser;
if(requiresAuth && !isAuthenticated) {
next("/reserveren")
} else {
next()
}
})
}
Then, in your nuxt.config.js add :
router: {
middleware: 'auth'
}

Vue Router beforeEnter vs beforeEach

I am trying to redirect non-logged in user from all pages to /login. I tried beforeEach() but it doesn't fire when user enter site with direct url like /home, /event.
Per-Route Guard beforeEnter() works perfectly since it fires once the user lands on that particular page. However, it requires me to add beforeEnter() on every routes.
I am looking for a way to duplicate that beforeEnter() on almost every page on the router (even on dynamic pages) which non-logged in user will be redirected to /login.
This one works when user enter with direct url /home.
routes: [
{
path: '/home',
name: 'home',
beforeEnter(to, from, next){
if ( to.name !== 'login' && !this.isloggedin ){
next({
path: 'login',
replace: true
})
} else {
next()
}
}
},
...
]
This one only works after user entered the site and route changed
vm.$router.beforeEach((to, from, next)=>{
if ( to.name !== 'login' && !this.isloggedin ){
next({
path: 'login',
replace: true
})
} else {
next();
}
})
Thanks in advance.
It looks like this beforeEach is being defined inside an initialized component, which means the first routing has already occured. Define it in the router module with your routes instead:
const router = new VueRouter({
...
})
router.beforeEach((to, from, next)=>{
if ( to.name !== 'login' && !this.isloggedin ){
next({
path: 'login',
replace: true
})
} else {
next();
}
})
Hopefully you are using Vuex and can import the store for store.state.isloggedin. If not using Vuex yet, this illustrates why it is useful for global state.
For a global and neat solution, you can control the router behavior in the App.vue using the router.beforeResolve(async (to, from, next) => {});.
beforeResolve is better than beforeEach, as beforeResolve will not load the component of the accessed path URL unless you fire manually the next function.
This is very helpful as you'll not render any interafce unless you check the authentication status of the user and then call next().
Example:
router.beforeResolve(async (to, from, next) => {
// Check if the user is authenticated.
let isUserAuthenticated = await apiRequestCustomFunction();
// Redirect user to the login page if not authenticated.
if (!isUserAuthenticated) {
location.replace("https://example.com/signin");
return false;
}
// When next() is called, the router will load the component corresponding
// to the URL path.
next();
});
TIP: You can display a loader while you check if the user is authenticated or not and then take an action (redirect to sign in page or load the app normally).

Middleware on specific page - NuxtJS

Well, I'm starting with nuxt and I have following routes:
/home
/dashboard
/login
I want to protect the /dashboard, but only for users logged in with a token in Cookie.
Then i created a middleware
/middleware/auth.js
import Cookie from 'js-cookie'
export default function({ req, redirect }) {
if (process.server) {
if (!req.headers.cookie) return redirect('/login')
const jwtCookie = req.headers.cookie.split(';').find(c => c.trim().startsWith('jwt='))
if (!jwtCookie) return redirect('/login')
} else {
const jwt = Cookie.get('jwt')
if (!jwt) { window.location = '/login' }
}
}
and register the middleware in my layout or dashboard page
<script>
export default {
middleware: 'auth',
}
</script>
when I access /dashboard apparently works perfectly
but the problem is that the middleware is being registered globally, it is running on all pages, all routes
So when you access /home that is a published page, if you do not have the cookie, you end up being redirected to login page
anyone help?
How about creating a condition based on the route.path param ?
export default function({ req, redirect, route }) {
if (!route.path.includes('dashboard')) { // if path doesn't include "dashboard", stop there
return;
}
if (process.server) {
if (!req.headers.cookie) return redirect('/login')
const jwtCookie = req.headers.cookie.split(';').find(c => c.trim().startsWith('jwt='))
if (!jwtCookie) return redirect('/login')
} else {
const jwt = Cookie.get('jwt')
if (!jwt) { window.location = '/login' }
}
}
Therefore you still benefit from the pre-render middleware system.
You probably have registered your middleware/auth.js in your nuxt.config.js.
When you register a middleware in nuxt.config.js, you're registering it globally, meaning it will be called for every route change.
Docs:
https://nuxtjs.org/guide/routing#middleware
In my opinion, you should call them plugin, because of
middleware called by each route changed also you can't use middleware in layout and subComponent, you can use it as plugin and call it manually everywhere also it's reactive and runtime.
path: /plugind/auth.js
import Cookie from 'js-cookie';
export default function({ req, redirect }) {
if (process.server) {
if (!req.headers.cookie) return redirect('/login')
const jwtCookie = req.headers.cookie.split(';').find(c =>
c.trim().startsWith('jwt='))
if (!jwtCookie) return redirect('/login')
} else {
const jwt = Cookie.get('jwt')
if (!jwt) { window.location = '/login'
}
}
}

Vue Router: URL does not load correct component while router-link does

My project uses Vue2 and Vue Router. I want to be able to load the component Stats by typing in the URL http://example.com/stats.
URL http://example.com/stats does not work, I'm redirected to / and it loads the App component
<router-link :to="/stats">Go to stats</router-link> works perfectly
I would like to know whether it is a Vue Router issue or a server configuration issue. I'd like to mention the fact that I experience this issue both in my localhost and my server using nGinx.
How could I fix this?
app.js:
const routes = [
{ path: '/', component: App },
{ path: '/stats', component: Stats },
{ path: "*", component: PageNotFound },
{ path: '/admin', meta: { requiresAdmin: true }, component: Admin},
{ path: "/not-authorized", component: NotAuthorized },
];
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes,
})
const app = new Vue({
el: '#app',
router,
data () {
return {}
},
});
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAdmin)) {
if (!Store.state.isAdmin) {
axios.post('/isAdmin').then((response) => {
if(response.data.isAdmin){
next();
}
else {
next({
path: '/not-authorized',
})
}
});
}
else {
next();
}
}
else {
next();
}
}
else {
next(); // make sure to always call next()!
}
});
Have you configured your web-server to return the same page regardless of the URL?
That way your app can load, and the URL is preserved so routing can take over and select the right component once it's loaded.
This answer https://stackoverflow.com/a/7027686/7816087 suggests the following config for nginx:
location / {
try_files $uri /base.html;
}
Go to your Laravel routes and put this:
Route::any('{all}', function () {
return view('index'); // if your main view is "index"
})
This will ensure that deep linking is working properly on all request handled by Laravel.
Here is what I did
Route::get('/stats', 'HomeController#home');

Categories