So, I guess this question is more academic than anything. I've been working all afternoon on a MEAN stack application's reset password functionality, and the general method I chose to employ is as follows:
In the login view, the user enters their username and clicks the forgot password button.
This submits a post request to the server's /forgot route, along with the { username: username } object.
The server looks for the user in the database, and if found, it creates a long string of random characters (e.g. '823uhr8824hriij3993') and saves the string as the user's remember token (valid for an hour, and the expiration is also saved).
An email is sent out to the user with a link to reset the password, corresponding to Angular route '/reset/:token' (continuing the example, '/reset/823uhr8824hriij3993').
If the user submits an updated password from that url before the token expires, the server checks the params for the appropriate remember token and their password is successfully changed.
I am using ng-Route, and my reset password route is configured as:
.when('/reset/:token', {
templateUrl: 'partials/account/reset-password.html',
controller: 'resetPasswordCtrl'
})
Unless I am missing something blatant (which is entirely possible), when the user hits the '/reset/823uhr8824hriij3993' route and Angular renders the reset-password.html view, it should be connected to the resetPasswordCtrl, should it not?
I spent a couple hours today trying to troubleshoot the username, password, and password confirmation validations that were not working, many of which are coded in the resetPasswordCtrl, figuring there must have been some typo somewhere causing a disconnect. But in fact the controller wasn't actually connected to the view until I put ng-controller="resetPasswordCtrl" in the topmost div tag.
All the other routes in this application are static and are set up via the $routeProvider just as above, and this is the first time I've run into this issue, so I suppose it must arise because of the dynamic /:token portion of the route. Anyway, my immediate problem is solved, but if someone wouldn't mind taking a moment to explain why it was a problem in the first place, I would really appreciate it... for future reference!
as I can see the problem is your reset password page come directly from server so the angular itself and routing you wrote do not work there because all the works handle by a server itself so if you want to use that functionality you should create a separate html file like('reset.html') with all tags and everything you need to load your app and controller then point it to servers response page
In that case when server going to serve reset page it's came up with actual page
Related
I am using MEAN Stack, and jade for html templating for developing a project. Since I am using jade all the .when() of the $routeProvider goes through the server and then rendered. Things are absolutely fine until recently I added $httpProvider.interceptor for authenticating each request. Basically, I started using JWT token based authentication and before requesting anything to the server, in my interceptor I am attaching 'Authorization' header. And the first middleware for protected apis I am verifying the token present in the 'Authorization' header. If present then proceed, else send authorization error.
Now, as mentioned in the title of the question. I have a few URLs containing hypen(-) between two words just to increase the readability.
eg: .when('/firstPart/secondPart1-secondPart2/thrirdPart', {
templateUrl: '/path/to/file'
})
this url is working fine if user going through the normal flow of getting to this url. The problem arises when the user comes to this page and hits the browser's refresh button, as he gets an error 'Authorization header not set'
I did a few research on what and why this is happening, I found the answer in
AngularJS not intercepting direct requests from Address Bar. According, to this answer and few other I understood that on refreshing browser makes a direct request to the server and doesn't go through angular routes, and thus, interceptor that is attaching the Authorization header to each request header is not getting called.
As, suggested by the same link, the workaround is that if auth verification fails make a call to '/', I donnot wish to do that as the user has just refreshed the page and he has to ideally get back the same page as he was in before he pressed refreshed. I am stuck here on how to do this.
Also, there is another mind–boggling this is if, I remove the 'hyphen'(-), and make it one word i.e., .when('/firstPart/secondPart1SecondPart2/thrirdPart', {
templateUrl: '/path/to/file'
})
everything works as expected even when the user hits the refresh button. It is first going through the angular router and interceptor attaches the Authorization header and then goes to make a get request for that template.
Wondering, is there any problem in using hyphen in URLs? However, I do not wish to remove the hyphens as I have already used it in many places and also I feel its good to have - between two words that needs to be displayed together in the URL than making them camel cased.
S, finally I have two questions :
1. How to load the same page as the user was in before he hit refresh, instead of redirecting him to '/' or login url.
2. The problem explained above, occurs only for hyphenated(-) URLs, what is the problem having '-' in the URL.
I am converting an app that used Parse as the backbone user database to Firebase. Parse always seemed to re-authenticate the user before any views were rendered or controllers executed. I.e. if you open a page in the site (even a deep linked page like www.mysite.com/admin/my_account_details),
Parse.User.current()
will return the current user - the Parse toolkit has re-authenticated (or cached) the current user's data. So controller code could depend on Parse.User.current() being a valid user object at all times, if the user was logged in, even when the page is opened deep into the site, say, via a bookmark.
Firebase seems not to work this way. In my .run() method I have something to the effect of:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// do something with current user
}
});
but this code gets executed AFTER controller code, which depends on the current user's info. In other words,
firebase.auth().currentUser
is returning no user, even though after firebase finishes loading, there will be a current user.
Am I correct in this diagnosis? And is there any way to ensure that firebase re-connects the current user before any controller code is executed?
When developing a web application with angular js, a part of time that developers spend is the time for implementing routing.
When using ui-router in a application, there are two "phases" to consider with regards to routing:
user navigates inside application: when click is made on some button, user is transfered to another state by using $state.go("somestate"). Parameters can be send etc. And url is changed accordingly.
user navigates directly via url.
Lets say application has such route:
/mythings/{thingid}/mysubthings/{mysubthingid}
If user navigates to that url directly by pasting it into browser window, application needs to handle it. My question is what's the best practice to do it?
What I'm thinging is: if looking at url example above what needs to be done when user enters that url in browser:
get {thingid} from url (from $stateParams), then get {mysubthingid} also from $stateParams (probably by using resolve (ui-router feature) when defining state), then inject what was resolved to controller and then make a query to api and get data about "subthing" and present view in ui with that data. So that should work with both "types of navigations": when user clicks and is transfered to state, or when user enter url directly into browser. Is this the right path to go?
And I suppose that any url you go to when you click something in application, you should be able to take that url and just paste it into browser and see the same results without being redirected to anywhere else. If application cannot handle every url in such way, maybe application' architecture needs to be reconsidered?
Thanks
In UI-Router, the main component of the routing is the state. The URL is essentially just an address that points to a specific state of the app. I don't think it's necessarily productive to think of the two ways of navigating as separate; they're just two sides of the same coin. There should be no URL that isn't handled by a state. Any URL that doesn't match a state should be caught by the otherwise definition on the $stateProvider and probably redirect to your home page or a 404 page.
In your example, the thing/:thingId/subthing/:subthingId url should map to a predefined state just like any other state. Let's say that state is main.subthing. The process for loading the data, initiating the controller and rendering the UI should be exactly the same whether you get there by calling $state.go('main.subthing', {thing: 123, subthing: 456}) or ui-sref='main.subthing({thing: 123, subthing: 456})' or you paste myapp.com/thing/123/subthing/456 into the browser. They'll all end up at exactly the same place with exactly the same data by calling the exact same logic (most likely loading thing 123 and subthing 456 in resolves and injecting those into a controller).
You're right that if a url can't be handled by the application, that's a sign that something is wrong. Like I said, bad urls should be handled by defining otherwise when setting up states. But pasting a URL into a browser shouldn't require any extra work if your states are defined correctly. URL handling is baked into UI-Router by default.
I partially agree with you. The point where I disagree is when the URL is obtained by a user who is not supposed to access it. Quite often some websites implement authorization code to check if the user who is currently accessing the page is authorized to do so.
Also I think the route could be a bit different. Something like:
{thingid}/{mysubthingid}
This, I think is a cleaner URL and the parameters could be handled in the same way as the one in your example.
I suggest this in order to make it a bit difficult to unauthorized users.
Anyway, it definitely depends on the kind of application you are implementing. If the app's requirement is to be able to access the page by pasting the URL in the browser then I guess your approach is much better.
I am implementing deep linking in a system using angular. (User follows link in to system, gets login screen, authenticates, then next step is the page they requested with the link (as opposed to the generic fresh-login-start page)).
In the $routeChangeStart event handler I store the next route location in the cookie. After the user authenticates I retrieve the location and send them there.
It works fine for urls without any path variables. For example, if they were trying to get to mydomain.com/viewAllServices then they go to the location post login.
It does not work for urls with path variables. For example, if they were trying to get to mydomain.com/service/123 then post login, they go to mydomain.com/service/:serviceId
I can see the parameters in the next.params and next.pathParams objects in my $routeChangeStart event handler. I can figure out how to replace them programatically, but I wonder if there is a friendlier part of the angular interface that I should be using.
Has anyone else implemented this? Is it necessary to put the values in the url using regex?
I am writing a small angular js app with different views. Some views are available to all users but few views are available to only logged in user. I have a small login form on top of my main page [note that there is no separate login screen].
Everything was working fine till here,till then I noticed that even though all the views are not available on my screen initially and will get loaded only once the user logs in. But if the user knows the url of the restricted views , he can bypass the login process.
I have found this stackoverflow question as something very similar to my problem Redirecting to a certain route based on condition. Please see the accepted answer.
But the issue here is that I don't have a separate login screen , so I can't use this code snippet given in the accepted answer
if ( next.templateUrl == "partials/login.html" ) {
// already going to #login, no redirect needed
} else {
// not going to #login, we should redirect now
$location.path( "/login" );
}
How can I achieve the same solution with an integrated login form since I don't have a separate url for my login screen?
I am using ui-router, and that provides a resolve attribute for every route. Whenever a route is accessed, the resolve part is executed first. It returns a promise, and the page does not get loaded until it is resolved. Here you can write some server side calls to validate user, and if invalid, just redirect to any valid page. You can write a resolve to every view and validate the user at every step. I used node/express sessions for storing the logged-in user data.