I'm having this problem with Vue Router.
My scenario is to allow / to be loaded first, fetch some data from there and then it will go to /chat/:chatId route and render UI there, where :chatId param is set from the data I got from API.
I have / and ['chat', 'chat/:chatId'] as route alias.
I have in-component guard for this matter.
beforeRouteEnter(to, from, next) {
store.dispatch('fetchOpenSessions')
.then(() => {
const firstChat = Object.keys(store.state.chatsidebar.openSessions)[0];
next({ name: 'chat', params: { chatId: firstChat } });
});
},
However this code ends up looping infinitely, causing the browser to hang.
My question is, how do I set chat/:chatId if my initial route is / or /chat without getting into infinite loop?
beforeRouteEnter(to, from, next) {
store.dispatch('fetchOpenSessions')
.then(() => {
if(to.name == 'chat'){
next();
}else{
const firstChat = Object.keys(store.state.chatsidebar.openSessions)[0];
next({ name: 'chat', params: { chatId: firstChat } });
}
});
},
Related
I have a function to authorize the user, so the user has restrictions on certain components. The function works well with the 'beforeEnter' navigation-guard. How to use/write the same function in the router beforeEach router-guard?
I tried writing the function in beforeEach but the javascript functions (forEach, includes,..) are not working in the router.beforeEach.
This is the function to authorize
function authorizeUser(to) {
const currentUser = store.getters["auth/isCurrentUser"];
console.log(currentUser);
currentUser.teams.forEach((team) => {
const validPermissions = team.permissions.filter((item) => { return to.meta.neededPermissions.includes(item.permissionType); }); //returns array of objects
const mappedValidPermissions = validPermissions.map((item) => { return item.permissionType; });// returns array with permissionType
// returned matched permissions
console.log(
JSON.stringify(to.meta.neededPermissions),
JSON.stringify(mappedValidPermissions),
);
if (!to.meta.neededPermissions.every(i=>mappedValidPermissions.includes(i))) {
router.push({ path: "/:notFound(.*)" });
}
});
}
This is the router.beforeEach nav-guard-
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.getters["auth/isLoggedIn"]) {
next({
name: "Authentication",
params: {
desiredRoute: to.fullPath,
},
});
} else {
next();
}
});
How to utilize the above function and if condition in beforeEach, so that I can check each router link before giving access?
What version of vue-router are you using. The current version's signature of beforeEach changed. Instead of calling next, you would optionally return either false or a route location object.
I have a dynamic page which shows the details of a product, the external server will return 404 if the requested product is not found, The problem is getServerSideProps shows a blank page instead of redirecting to 404
Here is the code:
// pages/[slug].tsx
export const getServerSideProps: GetServerSideProps = async ({
params,
res,
}) => {
const { product, relatedProducts } = await getProductDetail(
params?.slug as string
);
if (res.statusCode === 404) {
return {
redirect: { destination: "/404", permanent: false },
};
}
return {
props: {
product,
relatedProducts,
},
};
};
I tried also to use notFound property
if (res.statusCode === 404) {
return {
notFound: true
};
}
This is the first time I encountered the problem since server redirection was working pretty fine in other (static) pages
Help is much appreciated
From NextJS 10 onwards, you don't have to return your 404 page explicitly thanks to the new flag notFound: true. You can use it at getStaticProps and getServerSideProps to auto trigger the default 404 page or your own custom 404 page as well.
// pages/[slug].tsx
export const getServerSideProps: GetServerSideProps = async ({
params,
res,
}) => {
const { product, relatedProducts } = await getProductDetail(
params?.slug as string
);
const data = await res.json()
if (!data) {
return {
notFound: true,
}
}
// if (res.statusCode === 404) {
// return {
// redirect: { destination: "/404", permanent: false },
// };
// }
return {
props: {
product,
relatedProducts,
},
};
};
Doc References
notfound Support on Nextjs10
notfound on getStaticProps
notfound on getserversideprops
Custom 404 Page
I have a route like http://localhost:3000/admin/video/edit/5 and the controller looks like this
albumEdit: async (req, res) => {
const editInfoId = req.params.id;
await Movie.findOne({ where: { id: editInfoId } }).then((movie) => {
if (movie) {
res.render('admin/movies/edit', { title: 'Edit Movie On Page One', movie });
}
});
},
for the testing purpose when I type the wrong id after edit/ then the process is freezing after some time I am getting 500 errors.
how to prevent this if someone tries to break my app with the wrong id in the URL? I want something like if anyone tries to do this application redirect to an error page.
I am new in node js express js I need some info.
Your route will freeze if movie is falsy or if fineOne results in an error because for both of these cases you don't send any response.
after some time I am getting 500 errors.
If you run your node server behind a web server then this 500 is due to a timeout because your router does not send a response.
how to prevent this if someone tries to break my app with the wrong id in the URL? I want something like if anyone tries to do this application redirect to an error page.
As with any programming language or code, make sure you handle all control flows and possible exceptions.
Besides that, if you use await you in most of the cases don't want to use .then.
albumEdit: async (req, res) => {
const editInfoId = req.params.id;
try {
let movie = await Movie.findOne({
where: {
id: editInfoId
}
})
if (movie) {
res.render('admin/movies/edit', {
title: 'Edit Movie On Page One',
movie
});
} else {
// either the if is not necessary or you have to also handle the else cases
// send some error response
res.send('error')
}
} catch (err) {
// send some error response
res.send('error')
}
}
For completeness, this is how where you would need to do changes in your code, but as said above don't mix await and then:
albumEdit: async (req, res) => {
const editInfoId = req.params.id;
try {
await Movie.findOne({
where: {
id: editInfoId
}
}).then((movie) => {
if (movie) {
res.render('admin/movies/edit', {
title: 'Edit Movie On Page One',
movie
});
} else {
// either the if is not necessary or you have to also handle the else cases
// send some error response
res.send('error')
}
});
} catch (err) {
// send some error response
res.send('error')
}
}
This is my code for requiresAuth and requiresGuest
requiresAuth : Users who satisfy this cannot go to login page or signup page ( meta for / )
requiresGuest : Users who satisfy this cannot go to / or any other page having requiresAuth meta for /login and /signup
These 2 conditions are working perfectly fine for my page
Problem :
Step-1 Lets say i have been given a url like localhost:8000/api/createapi/.......
Step-2 So currently i am not logged in, I enter the above URL and it redirects me to the log in page (which is expected)
Step-3 But when i log back in it redirects me to / (which is not ideal )
What i want :
After Step-2 When i log in it should redirect me automatically to localhost:8000/api/createapi/.......
Since that was the requested URL in Step-1
router.beforeEach((to, from, next) => {
// check for required auth guard
if (to.matched.some(record => record.meta.requiresAuth)) {
requiresAuthLogic(to, next, from)
} else if (to.matched.some(record => record.meta.requiresGuest)) {
requiresGuestLogic(to, next)
} else {
// Proceed to route
next()
}
})
function requiresAuthLogic (to:Route, next:Function) {
// check if NOT logged in
if (!isUserLoggedIn()) {
// Go to login
next({
path: '/login',
query: {
redirect: to.fullPath
}
})
} else if (isUserEmailVerified() === true) {
// Proceed to route
next()
}
}
function requiresGuestLogic (to:Route, next:Function) {
if (isUserLoggedIn() && isUserEmailVerified() === true) {
next({
path: '/',
query: {
redirect: to.fullPath
}
})
} else {
// Proceed to route
next()
}
}
If I've understood correctly you need to use the value which is being passed via the redirect parameter
This should be done in your login function if login is successful, you haven't shared your login function but something like this:
loginUser() {
this.$store.dispatch('loginUser', {
email: this.email,
password: this.password
})
.then(() => {
this.$router.push(this.$route.query.redirect)
})
}
I have my routing working fine, using navigation guards so that user is not able to visit login or register routes once signed in.. However when I type in in addres bar /auth/signin, login screen does appear shortly before redirecting to dashboard (as it detects in beforeEach that the route is requiresGuest).
router.beforeEach(function (to, from, next) {
// prevent access to login & register after signing in
if (to.matched.some(record => record.meta.requiresGuest)
&& auth.user.authenticated)
{
next({
path: '/dashboard'
});
}
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!auth.user.authenticated) {
next({
path: '/auth/signin',
query: { redirect: to.fullPath }
})
}
}
next() // make sure to always call next()!
});
Is there a way to prevent component from flash-appearing like that!?
Isn't that beforeEach triggered before the component is even created?
Change your if else conditional statements.
router.beforeEach(function(to, from, next) {
// prevent access to login & register after signing in
if (to.matched.some(record => record.meta.requiresGuest) && auth.user.authenticated) {
next({
path: '/dashboard'
});
} else if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.user.authenticated) {
next({
path: '/auth/signin',
query: {
redirect: to.fullPath
}
})
}
} else {
next() // make sure to always call next()!
}
})