Do not load directive for certain route(s) - javascript

I'm attempting to build a 'signin' page for my app that loads whenever a user is not authenticated. The navbar and footer in my app contain data which can only be loaded for authenticated users. Therefore I would like to conditionally hide the navbar and footer directives whenever my route is /signin.
Here is the body of my index.html:
<body ng-app="gameApp">
<dm-navbar ng-if="!$root.notAuthenticated"></dm-navbar>
<ng-view></ng-view>
<dm-footer ng-if="!$root.notAuthenticated"></dm-footer>
</body>
...and in my signinController I set $rootScope.notAuthenticated = true
This successfully removes gm-navbar and gm-footer from the DOM. However, the controller logic associated with these directives still fires (as I see 401 errors in the console).

Well there are a couple of ways. Are you keeping state of the logged in user in some object. Like the controller for /signin holds $scope.userInfo? If so, you can just do :
<gm-navbar ng-if="userInfo"></gm-navbar>
This will hide the directive if the userInfo variable is loaded with the logged in user. This way, you can abstract this approach to all pages that need to hide this, not just /signin
How you populate the user info is up to you, but let's say you're using JWT, you would send a /GET request to the server with the token, and the server would respond with user info, etc.

Related

How to use *ngIf correctly?

I want to use *ngIf in my angular project. I use app.component.html to handle login page and as well as dashboard. So I want to hide dashboard before user login to the website. After user logged to the system I want to show the dashboard.
So I use *ngIf to handle this. I use following code to handle the case.
In my app.component.html I use following div to show when ever user is not log to the system.
<div class="login-page" *ngIf="!isLog()">
... go some code here...
</div>
And following div is use to show the dashboard after user is log to the system.
<div class="main-dashboard" *ngIf="isLog()">
... go some code here and router outlet as well ...
<router-outlet></router-outlet>
</div>
Finally in my app.component.ts file is use isLog() method to check whether user is logged or not.
isLog(){
// Use to back end api to check user log
var log : boolean = false;
// If User is Log
// Use back end api to handle this
log = true;
return log;
}
But the issue is when user try to log to the system for first time this code structure works fine for that case. But after user log to the system if user refresh the page for little time (0.5 ms > time) system shows the login page and suddenly shows the current page.
I think this is because every time user refresh the page website try to check user is log. During that time isLog() method return false so website shows login page for that time.
After isLog() return the valid value it means true. Then it shows the dashboard.
But I want to avoid this case. After user log to the system I don't want to show login page even for little time. Because user get confused.
How can avoid this case? Is there are any possible way to handle this type of issue?? OR recommended way???
If that's the case, try to store this info in sessionStorage which will persist the data for that tab and you wont have to wait for server response.
Also, as a side note, using *ngIf="isLog()" is not a good approach. You can try to put console.log in isLog() and you'll see it getting triggered periodically. That's because of change Detection cycle of angular which works on all the expressions assigned to template, and since *ngIf has function associated to it, that function (isLog()) is executed.
Its better if you can evaluate this value on ngOnInit and assign it some variable which will be used as a flag to check *ngIf condition
Of course it depends on your needs but the best practise is making the login page a seperate component and use Route Guards to protect the routes.
If having it in the same page and using ngIf is enough for your requirements which means you have a small application and it is not likely to expand, it is fine. The problem you experience is well explained by #Shashank Vivek in his answer.

ReactJS - how to setup login pattern?

I'm sorry if this question is a bit vague, but I'm tackling this problem for the first time and any pointer would be useful.
I am building a web app using ReactJS and I need a login system - first page with two fields username / password and submit button. The server returns a token (1234) and this needs to be used in an auth header (Authorization: Bearer 1234) in order to access the protected area.
How should I handle the login and make the browser update itself with the new content available after login?
As the others have pointed out, it is a good idea to use React-Router.
I think you can use pattern like this: You get user inputs and send them via AJAX (with JQuery, Superagent, whatever you want). If the input is valid and user authenticated, the server sends back token with some user info, which can include his roles or permissions. Based on these received data, you can use React-Router to render other component, e.g. welcome page (by calling replaceState on React-Router history object - in flux action for example).
Additionally, you should save this token in a cookie or into a session/local storage (in order to be able to use it on every subsequent request), and the user info could be stored in a Flux store. After saving this user the store emits change event, which should lead to rerender of your root component with the user information you got.
Then, based on the new user roles or permissions in your store, you can have for example ES7 decorator on some of your components deciding, if it displays the actual component or not.
Hope it helps you a bit.

How to create session inside Loopback app with an AngularJS client?

Here is my problem :
I'm creating a web app with loopback (great framework :) ) with an AngularJS client, everything works well but impossible to reload the page without being disconnected. This behaviour is normal, however I would like to persist the session with a "Remember me" checkbox and just avoid to be disconnect on page reload. The access token is stored in localStorage, I think I have to create a cookie on myself but the main point, how do I avoid disconnection ? And redirection to forbidden page. Then should I do this on server-side or client-side both ? I'm lost actually...
I did start from this application on github if you wish to have a better idea of the project:
https://github.com/strongloop/loopback-getting-started-intermediate
You shouldn't need to create a separate cookie to store the authToken if it's already in localStorage. The part you will need to modify is inside app.js, the .run() block, which checks for the existence of $rootScope.currentUser to determine if you're logged in, which will not be persisted across browser reloads.
The code creates $rootScope.currentUser in Auth.js. The .run() block of app.js simply checks for the existence of $rootScope.currentUser to determine if you are logged in.
So you'll need to change how you detect logged out state from simply checking for $rootScope.currentUser to attempting an actual call to User.getCurrent() or something. If you are logged in, the call will include the auth token in the headers, if not, you'll get a 401 status code response and you can redirect to the login page in that case.

Secure response from Rails to AngularJS

Please helpe me, I want to show an html element if user is admin else hide the element,
Example:
AngularJS:
$http.get('users.json'})
.success(function(data){
//data user return true and the value true represents admin
$scope.user = data.user;
});
HTML:
<h1 ng-show="user">Hello Admin</h1>
The problem here, anyone can open firebug or devTools and change user scope value.
You are absolutely right in guessing that the above method is not at all secure.
The solution is to either send the local data to the server and get it to return the secure content which is then dynamically injected into the dom.
i.e. Your Admin relevant stuff is not always present on the client side, and only after authentication is it fetched (via AJAX probably) and rendered.
This makes your app a bit more secure.
You might also want to look into the following mechanism for secure authentication on client side apps:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/

Load initial data after log in with an angularjs app

I have a completely separate (from backend) AngularJS app. It uses tokens (JWT) for authentication. I'm also using ui-router and Restangular.
My problem:
I have a sidebar/profile area that displays information from the currently logged in user on every "page". It is implemented as a directive+controller and is outside of the ui-view directive context. Inside of the controller for this sidebar I'm making a request to get the profile information and attach it to the $scope. Now, when a user first visits the app that sidebar and controller get invoked and the request is made to get the profile information. However, if and since the user is not logged in, the request fails and no data is bound with the $scope.
In the meantime (notice this all happens really fast), the event listener (listening for $stateChangeSuccess from ui-router) determines that the user is not logged in (essentially if they don't have a token) and does a $state.go('login') to forward the user to the login view. The user logs in, and a $state.go('dashboard') is invoked to bring them back to the dashboard. However, being that sidebar is outside of the context of the router the controller for it is not instantiated again to cause a new request for profile information. So the sidebar is just empty with no profile information.
I'm aware that there are going to be several possible solutions to this, but I'm trying to find a descent one.
How would you architect an angular app in order to solve or avoid the problem I'm having?
P.S. I think I may be having analysis paralysis over this.
It's hard for me to answer without seeing your code specifically. If I understand correctly your directive is firing prior to the user logging in, and since there is no user profile, the side bar doesn't initiate correctly. What I would suggest is possibly doing an ng-if on the tag that fires the directive something like:
<side-bar ng-if='userData' />
That way the tag isn't inserted into the DOM until the userData exists and therefore doesn't fire the directive on the login page.
Assuming that the sidebar is the highest angular controller in your application and the other controllers are nested inside it you should be able to put a function on it that will load the information that you need. Then you can call $rootScope.loadme() anywhere you inject $rootScope.
var mainMod = angular.module('mainMod',[]);
mainMod .controller('mainController', function($scope)
{
$scope.loadMe = function()
{
//load stuff here
};
$scope.loadMe();
});
mainMod .controller('secondController', function($rootScope, $scope)
{
$rootScope.loadMe();
});
SudoCode probably wont work with copy paste but the idea should be sound.

Categories