When component introduces new route for its router-view it is working while going trough the app, but once you refresh or try to access url directly it does not load. I assume that it is because of the fact that component adding routes did not add them yet.
But I would expect that router would parse url by its segments, match parent component, loads it (which introduces child routes) and then continue with next segment. Or something similar.
Is there a way how to achieve routing added lazily? So each loaded module introduce its part (module) of a router? But in same time they can be accessed by url?
Thanks
Here is reproduced issue: https://codesandbox.io/s/vue-3-router-lazy-route-5opufo
Click on Admin link and then settings, it works, try to access admin/settings by url, it does not load settings content.
EDIT:
Here what I expect https://stackblitz.com/edit/angular-vwnzjg
ATTENTION it fails on stackblitz, but you can download the project, install dependencies and try it yourself to see that it works correctly.
After start dev server, navigate directly to http://localhost:4200/customers/profile as you can see, it works even the fact that the router part targeted is loaded lazily in Customers module.
When you click on admin and then click on settings, the code run follows this scenario:
Click admin -> router resolved (found admin component) -> admin component setup -> you dynamic add settings router
-> click settings -> router resolved (found settings component) -> load settings component successfully
But when you reload the browser on the /admin/settings route, the scenario will be:
Reload page '/admin/settings' -> router resolved (found admin component but NOT the settings component because admin component's setup code is not run yet)
-> only load admin component
In this scenario, the admin component's setup code will be run after the router is resolved. So the dynamic adding router code is not run at that time and the router can NOT resolve the settings component
Solution
Move your dynamic adding router code to beforeEach navigation guard so it can be run every time the router resolved
router.beforeEach((to, from) => {
const hasRoute = router.hasRoute(to.name || "");
if (to.path === "/admin/settings" && !router.hasRoute(to.name || "")) {
router.addRoute("admin", {
path: "settings",
name: "settings",
component: { template: "<div>AdminSettings</div>" }
});
// Don't forget to return the router here to make sure the router will be correctly resolved
return { name: "settings" };
}
});
Related
I am using Auth0 NextJs SDK for authentication in my NextJS App. I am following this tutorial https://auth0.com/blog/introducing-the-auth0-next-js-sdk/. In my local machine, everything works fine.
The configuration for Auth0 in my local server:
AUTH0_SECRET=XXXXX
AUTH0_BASE_URL=http://localhost:3000
AUTH0_ISSUER_BASE_URL=https://myappfakename.us.auth0.com
AUTH0_CLIENT_ID=XXXX
AUTH0_CLIENT_SECRET=XXXX
In the Auth0 Dashboard, I added the following URLs :
Allowed Callback URLs: http://localhost:3000/api/auth/callback
Allowed Logout URLs: http://localhost:3000/
My local app works locally fine.
I uploaded the app on Vercel. And changed the
AUTH0_BASE_URL=https://mysitefakename.vercel.app/
In Auth0 Dashboard, updated the following information:
Allowed Callback URLs: https://mysitefakename.vercel.app/api/auth/callback
Allowed Logout URLs: https://mysitefakename.vercel.app
I am getting the following error:
Oops!, something went wrong
Callback URL mismatch.
The provided redirect_uri is not in the list of allowed callback URLs.
Please go to the Application Settings page and make sure you are sending a valid callback url from your application
What changes I should make it works from Vercel as well?
You can try to check if vercel isn't changing the url when redirecting to auth0. Your configurations seems good to me. The error is very explicit though. I think a good option should be to verify that the redirect (if handled by vercel) is doing with the same url as auth0 expects.
And don't forget to add the url you're currently on when performing the callback. Are you in https://mysitefakename.vercel.app/api/auth/callback when the callback is executed? (call auth0).
you have to change your base url in the env.local file
AUTH0_BASE_URL=https://mysitefakename.vercel.app/
you can also make two more env files namely env.development and env.production and set different base urls for different cases so that the correct base url is automatically loaded depending on how ur web app is running.
You need to add handleLogin under api/auth/[...auth0].js and that will solve it:
import { handleAuth, handleLogin } from '#auth0/nextjs-auth0';
export default handleAuth({
async login(request, response) {
await handleLogin(request, response, {
returnTo: '/profile',
});
},
});
Don't forget to also add allowed callback url in [Auth0 Dashboard]: https://manage.auth0.com/dashboard for your hosted app for both local and hosted instance:
http://localhost:3000/api/auth/callback, https://*.vercel.app/api/auth/callback
In a previous Stack Overflow question, I shied away from using an external webhook on Actions on Google
so I needed to go back to the inline editor. I got that worked out, but now I'm feeling brave again.
I've outgrown the inline editor and want the ability to develop my code on my laptop, testing it in Firebase, and publishing to a site for my webhook, presumably where the inline code editor publishes to. In fact, I have already written the require functions and deployed them from Firebase. So the full functionality is ready to go, I just need to hook it up properly to Actions on Google.
What I have now in Actions on Google, inline editor, is more of a stub. I want to merge that stub into my more fullblown logic that I have in Firebase. Here is what is in the inline editor:
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
const app = conversation();
app.handle('intent_a_handler', conv => {
// Implement your code here
conv.add("Here I am in intent A");
});
app.handle('intent_b_handler', conv => {
// Implement your code here
conv.add("Here I am in intent B");
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
When I search on the Internet, I see discussion from the point of view of Dialogflow, but like I say, I'm in "Actions on Google". I want to transition away from the inline editor, taking what I already have, as a basis.Can someone explain how I set that up? I'm happy to do this within the context of the Google ecosystem.
To test your own webhook locally on your own system I would recommend incorporating a web app framework such as express. With express you can host code on your local machine and make it respond to request from Actions on Google. In your case you would replace this will all the code related to the Firebase functions package. Here is an example of what a simple webhook for Actions on Google looks like:
const express = require('express');
const bodyParser = require('body-parser')
const { conversation } = require('#assistant/conversation');
const exprs = express();
exprs.use(bodyParser.json()) // allows Express to work with JSON requests
const app = conversation();
app.handle('example intent', () => {
// Do something
})
// More app.handle() setups
exprs.post('/', app);
exprs.listen(3000);
With this setup you should be able to run your own application locally. The only thing you need to do is install the required dependencies and add your own intent handlers for your action. At this point you have a webhook running on your own machine, but that isn't enough to use it as a webhook in Actions on Google because it runs locally and isn't publicly available via the internet.
For this reason we will be using a tool called ngrok. With ngrok you can create a public https address that runs all messages to your local machine. This way you can use ngrok address as your webhook URL. Now you can just make as many code changes as you want and Actions on Google will automatically use the latest changes when you develop. No need to upload and wait for Firebase to do this.
Just to be clear: Ngrok should only be used for development. When you are done with developing your action you should upload all your code to a cloud service or host it on your own server if you have any. A (free plan) ngrok URL usually expires every 6 hours. So its not a suitable solution for anything other than development.
I read a lot of questions about 'history.push nginx react-router' but I didn't find the solution for the problem I'm facing.
The problem is, when I log in my application in my Login component I do something like this after the ajax call is executed:
cb = (res) => {
if (res.token!== null && res.token !== undefined){
localStorage.setItem("token",res.token);
localStorage.setItem("expiresIn",res.expiresIn);
localStorage.setItem("email", res.email);
**history.push('/home/0/0');**
}else{this.setState({errorTextMail:"wrong mail or wrong password!"})}}
Locally it works fine but in the console the history.push('/home/0/0') fires a request that nginx doesn't handle and return 404, but in my browser the app log me in and I don't see the error.
Instead when I build the app and put the build folder under nginx to serve static files, when I try to login it show me the 404 page. Then if I refresh the page (removing the /home/0/0 from the url) it works fine, recognize the token and log me in and I can browse other route of the app.
I was supposed that history.push would have been handled by react-router, just changing the component mapped by the appropriate <Route path="/home/:idOne/:idTwo" component={Home} /> component and not firing a new request to nginx.
My question is, there is a way to switch compoent when the cb function return my token instead of using history.push('/home/0/0')?
Note the history object is defined this way
import history from './history';
and the history.js's content is :
import createHistory from 'history/createBrowserHistory'
export default createHistory({
forceRefresh: true
})
Thanks for any suggestion.
In my angular2 application i have two components (profile / projects) so my routes are like
{ path: 'profile', component: ProfileComponent },
{ path: 'projects', component: ProjectsComponent }
and i need to integrate angular 2 in existing struts application where all urls are having .do as url extension
so i have updated my routes to
{ path: 'profile.do', component: ProfileComponent },
{ path: 'projects.do', component: ProjectsComponent }
when i launch my application directly with localhost:3000/profile.do i am getting Cannot GET /profile.do error
where as when launch application using localhost:3000/ and click hyper link my profile it works
Any suggestion or solution to access my application with localhost:3000/profile.do url
When you hit localhost:3000/profile.do it goes directly to server and tries to resolve the resource, if appropriate redirects are not set on server side you will get errors saying resource not found, Angular routing kicks only after the default page is loaded, this is why it works when the page is already loaded and you hit hyperlink.
Set appropriate redirects on server side.
Hope this helps!!
I want to verify that I am placing my Iron Router code in the correct location. Right now I have it stored in lib/router.js, which means the code is shared on the client and server. Is that correct?
Also, some of my routes require admin status, such as:
Router.route('/manage', function () {
if ($.inArray('admin', Meteor.user().roles) > -1) {
this.render('manage');
} else {
this.render('403_forbidden');
}
});
Is that code safe in its current location? I am also interested in knowing how I can test these kinds of security holes so that I don't have to ask in the future.
Thanks
As to location of router.js ...
Yes, you want it to be available on both the client and server. So putting inside the /lib directory is fine. Really, you can put it anywhere other the the /client or /server directories.
FWIW, in most projects I've looked at, router.js is stored in the top-level project directory. Possibly this is to avoid load order issues (i.e. if the router has some dependencies on files in /lib, /client, or /server, which will generally be loaded before top-level files), or possibly its because everyone I've looked at is working off the same boilerplate code. Check out the Meteor official docs if you want to know more about load order.
As for your admin question, that route should be OK. You can test it by opening up a client side console like firebug and trying something like :
Meteor.users.update(Meteor.userId(), {$set: {roles: ['admin']}});
I believe users can only update fields in the Meteor.users.profile, so this should fail. If it doesn't, you can just add the following deny rule (in client + server);
Meteor.users.deny({
update: function() {
return true;
}
});