We have a backbone model that represents the user's account. Data for this model comes in via an API call to our backend.
If the user is logged in, the server returns account data and everything works fine. If the user is not logged in, the backend returns a 401. I want to have backbone handle this in some way, and use a hard coded "anoymous" data in place. How can I do this?
Would it be a better approach to modify the backend to return the dummy data instead of returning a 401?
edit: By 'handle' I mean I need to be able to run this code:
$.when(Account.fetch()).then(function() {alert("needs to be called");}
currently, the 401 causes the then clause to not get called.
Backbone models have defaults property. Would it work for you?
Related
I am building an sample application that lets user store comments.
I've created the registration and login process. When the user registers, his details are stored in a MySQL database and a token is returned to the browser. Now he can access the Profile page.
When an existing user logs in he is redirected to the profile page. The profile page is accessible only when a user registers or logs in.
After logging in, I want to show all his comments if he has already added them.
My frontend is in Angular and backend use Laravel. For authentication I use Satellizer.
I want to know, what is the best approach while playing with data, considering the fact that the user will add, edit his comments. Should I use localstorage and store data in a key value pair or should I create a json file which gets updated everytime the user adds a comment or makes a change.
I wanted to know what is the most efficient way to deal with data from server so that the application is fast even when it scales to a 10000 users and lot of data for each user.
Thanks
You should be updating it on the server when changes are made rather than only relying on localstorage. You can use localstorage to cache, but it should only be for immutable data, it shouldn't really be used for data that is going to change.
So in this case you'll be adding and updating new comments via your API (ideally a RESTful one!). Once you've made a change, you could store the comments locally and only update them when the user makes a new comment, however you'll quickly run into issues where the data is invalid on different clients. (i.e. if you update the comments on a different computer, the other computer won't be aware).
Alternatively, you could cache the comments and then simply ping the server to find out if new comments have been added. This could be using a HEAD request for example to check the last modified date on your comments resource.
You can store comments data locally on user browser, but you should properly manage it.
I don't how much load your server will have and if the time invested now worths it.
You can fetch comments and store them locally
User adds a comment, then you update locally and send a request to the server
You need to track the request response, if requests fail so notify user and remove comments from local.
if request was successful so you can continue on your way.
** facebook uses this "success first" approach
user does an action, and he see it happens instantly, in the background it could take few seconds, only if it fails they will notify you.
** look at their commenting process, when you comment, it appears instantly, no loading... but in the BG the load happens.
I am curious how others are solving the following problem...
I have an angular application that requires user authentication. The user must log in to the system to make requests. The user must also be authorized to create a socket.io connection.
When the application first starts up I must determine if the user is already authorized. I was planning on looking in sessionStorage for a user object/token. Does that make sense? And if the user is not authorized, the application will make a request to get the current user. If/When that fails, a 401 error is returned and angular intercepts/prompts for a username/password.
Given that there are two different code paths for authentication (check sesssionStorage vs make a request and wait for the response) how do you trigger the requests for all the other information that is required for the application? Do you emit/listen to a LOGIN event that gets broadcast in both scenarios?
My plan was to wrap the socket.io connection attempt and the ".on(...)" calls inside of the LOGIN event, does that make sense?
And if you want to listen to socket.io events or grab information from the server in a controller that is loaded after the LOGIN event has fired, how do you trigger the data from being retrieved from the server?
Sorry for the long winded questions, but I've hit a road block and I'm wondering how others are managing all the authentication and different pieces of information that is required to get from the server.
Ok, I guess let's go in order of question asked.
Does it make sense to use sessionStorage to hold user auth info?
Yes. You will need to decide between local/session Storage depending on how you want it to work. We decided we wanted the session to still be active for the time period that the backend recognizes, so even if the user closes the browser and reopens it, they will be logged in, and so we opted for localStorage instead of sessionStorage.
How do you trigger the requests for all the other information that is required for the application? Do you emit/listen to a LOGIN event that gets broadcast in both scenarios?
After login, we redirect the user to the "landing" page (route). All of our route/state changes wait on a resolve function which is doing the session auth. We only store the session id in localStorage. After the successful state change, the controllers that go with the newly loaded views start requesting data from our services. All of our controllers are designed to load data on init. So no, we do not use events. It feels like events should be used only as a last resort - and that is also the impression I get from core Angular devs since I get chastised for event usage in pull requests :)
My plan was to wrap the socket.io connection attempt and the ".on(...)" calls inside of the LOGIN event, does that make sense?
Maybe. I am not using socket.io outright, but instead have been experimenting with atmosphere (mainly because we had a java backend requirement). I do initiate the connection in the login success handler. But the general atmosphere event handling I have put into an application-level controller that is on <body>.
And if you want to listen to socket.io events or grab information from the server in a controller that is loaded after the LOGIN event has fired, how do you trigger the data from being retrieved from the server?
I could imagine (again using an app-level controller, or a service, or in my case, likely both) a function that returns the socket.io connection. A controller that has come into being could grab the socket.io stuff on init, and setup the listeners for the events that it is interested in.
My advice is to get all of your session and auth stuff worked out first, especially with regard to how you are going to do routing. Once all of it is working to your satisfaction, then add the socket.io stuff in. I realize that this might not be possible in all cases because perhaps you need something from the socket.io connection that is critical to your app even at an early stage.
Parts of my app require user validation which is done either automatically (using an existing refresh token stored as a cookie) or manually using a login form.
While I can implement this using a Service it feels rather hackish (the various services are designed to return data). But I can't think of a better way to share capabilities between different controllers.
P.S
I did check out https://github.com/witoldsz/angular-http-auth but catching the 401 error and initiating a login means that I will make an extra call even though I can tell it will fail.
I think you can definitely break up the login process into a service, as it can be incredibly important to store and pass info to various controllers in your app, and this is precisely what services are for.
I have created a bug-reporting app using something similar to that link you pointed out, but I customized it using a service and a controller as well. These are the steps I followed as I set it up:
First, I set up the interceptor to catch the 401 errors and
broadcasts a message that login is required.
I then set up an authService to log all those bad 401 calls. If
there is a bad call, it gets stored.
I also have a login controller that also uses the authService than
handles the form, registration, login, logout, etc etc. The
controller is used in the menu on every page, so there is no chance
that a broadcast event could be missed. My controller listens for
the broadcast event, and when received, displays the login form.
After a successful login, I tell my authService to repeat all those
stored calls and delete them.
Now this works great, but what if someone refreshes the page, the authService is deleted, and the interceptor will have to do all the work again, events will need to be broadcast, and ultimately it is a pain. To overcome this I did a simple check in my login controller.
First just check to see if the authService has the user object stored.
If not, do a check with the server, if the result is that the user is logged in, populate the authService again.
If the user is not logged in, do nothing, but let the authService know that you have checked against the server and seen that the user wasn't logged in.
Again, in my case I didn't want to force users to log in unless they were trying to perform specific actions that required a login. As a bug-reporting app, I wanted to allow anonymous users to read content, but as soon as they were going to post they had to register or login.
If your case involves being logged in 100% of the time, you can completely ignore the interceptor. Just set up a service and a controller. If the login controller sees that the authService isn't populated, redirect to the login screen. Upon refresh, do a simple check against the server to ensure they are still logged in, otherwise redirect to the login screen.
A service is very appropriate in this case. As described in this video about best practices, Services aren't as much about "Getting data", as it is separation of logic from the controller. A controller says what to do, a service says how to do it.
So, in your case, a Controller says "I need to check if the user is authenticated" but to know how to do that, it depends on a service.
This fits perfectly with the data-gathering concept as well. A controller says "I need to get all of the Employee Information." The service defines how.
He specifically says in this meeting that whenever there is information that needs to be shared between controllers, a service is pretty much always the best way to do it.
How do you prevent people from reaching certain routes, for example, edit and delete, if they are not registered, or not authorized?
In other words, how can I make so that the router rejects or redirects calls like:
http://appname.com/#/photo/1/edit
without duplicating the validation logic?
What I see as a very buzzing problem is the following: if I go to the aforementioned url, my router method won't bother to fetch info from the server if I have the photo model already (because this is what stateful apps should do, right ). However, now there is completely no way to tell if the current user is the owner of the photo (to be able to edit), unless the router method checks explicitly if their IDs match ... which is already duplication of the validation logic (because the server always makes a validation).
Dilemmas like this are simply ruining my day
Your models shouldn't be doing any authentication logic. If you have the logic in your server-side code, what's the problem? Your server should return unauthorized (401 or something similar), and then your model can respond appropriately (e.g., printing an error message to the user).
I am trying to create a mixpanel funnel using PHP backed which includes following events
Home Page Viewed
Signup
Dashboard Viewed
Submitted Code
Currently I am doing this w/o using distinct_id and thus mixpanel trends are pretty accurate but funnel which depend upon unique user count gives false data.
How should I use distinct_id property to solve this problem?
I'm not a PHP developer, but I'm working with Mixpanel at the moment and just encountered a similar problem. You have two options- either force a unique identifier on the frontend that you can also determine easily on the backend (such as a user's ID), or use the default Mixpanel-provided identifier when you make calls from the backend. The first option can cause some consistency pitfalls, particularly if you're trying to create a funnel involving something like user signup. The second option, however, is fairly foolproof:
Mixpanel sets a cookie named "mp_YOUR-PROJECT-TOKEN-HERE_mixpanel" for each user. That cookie contains, among other things, the distinct_id that Mixpanel is using for that user on events triggered from the frontend. If you extract that value from the cookie and explicitly pass it as the distinct_id param to your Mixpanel calls on the backend, you should get consistent flows and working funnels.
Note that, for ease of use, Mixpanel also allows you to set cookie_name as an argument to set_config or init in the frontend javascript:
mixpanel.init("PROJECT-TOKEN-HERE", {cookie_name: foo})
Though for some reason that gives you a cookie named "mp_foo" instead of just "foo". At any rate, best of luck.