location on change view issue angularjs - angularjs

Stuck in an issue where i have to check authentication when location changes:
Issue:
while on location change i request the back-end to check auth if response is not 401 then show the page otherwise redirect to login page, when response is 401 the page shows for a bit and then the redirection happens to login page , for me its a headache because the page shows for a bit and then location changes , someone help me please?
$rootScope.$on('$locationChangeStart', function (event, next, current) {
var publicPages = [''];
$rootScope.showPreloader = true;
AuthenticationService.Login(function (_data) {
if (_data.result) {
count =1;
localStorage.setItem('userInfo', angular.toJson(_data.result));
awtcDataService.employeeInfo = _data.result;
var roles = awtcDataService.employeeInfo
var route = localStorage.getItem('setRoute')
if (route == '/check') {
$state.go('help');
}
else {
$state.go('home');
}
}
if (_data.status === 401) {
$state.go('login', {reload: true})//shows the page e.g home and then redirects to this page
count =1;
event.preventDefault();
return;
$timeout(function(){
console.log("show after directive partial loaded")
});
}
else {
}
}, function (error) {
if (error.status === 401) {
$state.go('login', {reload: true})/shows the page sometimes e.g home and then redirects to this page
count =1;
event.preventDefault();
return;
$timeout(function(){
console.log("show after directive partial loaded")
});
}
});
});

All state events, (i.e. $stateChange* and friends) are now deprecated and disabled by default. Instead of listening for events, use the Transition Hook API.
https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-change-events

Related

response.redirect() is not working in express (NodeJS)

I want redirect to dashboard.html from login.html if username is correct, if not then alert box will be shown, I used both express response.redirect('path') or response.sendFile('path') but none is working here.
I am using angularJs as front-end and express module of nodeJs in back-end.
Express route code:
module.exports = function(app,db,path){
app.post('/student-login', function (request, response) {
var user = request.body;
if(user.username == "abhinav")
{
response.redirect('/views/dashboard.html');
response.end();
}
else{
response.send("Wrong username");
response.end();
}
});
}
AngularJs code:
angular.module('loginService',[])
.service('loginService',function($http){
return {
sendStudent : function(data){
return $http.post('/student-login',data)
.then(function(response){
return response.data;
});
}
}
});
AngularJs controller Code:
if ($scope.myForm.$valid)
loginService.sendStudent($scope.studentData)
.then(function(data){
if(data=="Wrong username")
alert(data);
});
Developer option > Network :
As you can see in the Network tab, browser does make a request to the /views/dashboard.html route. It means that redirect is working. The reason why you don't get the expected behavior is because you need to navigate to that page (right now you are simply loading content of the page).
I would suggest moving redirection logic from express to frontend and using http status codes to signal login errors.
Express code:
module.exports = function(app,db,path){
app.post('/student-login', function (request, response) {
var user = request.body;
if (user.username == "abhinav") {
response.sendStatus(200);
} else {
response.sendStatus(401);
}
});
}
AngularJS controller code:
if ($scope.myForm.$valid) {
loginService.sendStudent($scope.studentData).then(() => {
// login successful, response status is 200
location.href = '/views/dashboard.html'
}).catch(response => {
if (response.status === 401) {
alert("Wrong username")
} else {
alert("Some other error")
}
})
}
I'm using location.href as an example only because I'm not familiar with angularjs routing. It will reload the whole page, use API provided by angularjs router if you want to avoid that.

How can I get protractor to wait for a login before proceeding?

I have a non-angular entry page to my app and I'm trying to first login:
describe('Authentication', function() {
it('should authenticate a user', function() {
browser.driver.get('https://example.com')
browser.driver.findElement(by.id('username')).sendKeys("user");
browser.driver.findElement(by.id('password')).sendKeys("mypass");
browser.driver.findElement(by.tagName('input')).click()
var url = browser.getLocationAbsUrl()
browser.driver.sleep(1)
browser.waitForAngular()
return
})
})
However, this gives an error:
Failed: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or bec
ause your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
What can I do to resolve this?
I wrote some helpers in the past to get this work in my e2e-tests:
waitForUrlToChangeTo: function (urlToMatch) {
var currentUrl;
return browser.getCurrentUrl().then(function storeCurrentUrl(url) {
currentUrl = url;
})
.then(function waitForUrlToChangeTo() {
browser.ignoreSynchronization = true;
return browser.wait(function waitForUrlToChangeTo() {
return browser.getCurrentUrl().then(function compareCurrentUrl(url) {
browser.ignoreSynchronization = false;
return url.indexOf(urlToMatch) !== -1;
});
});
}
);
},
login : function (username, password, url) {
browser.get('#/login');
element(by.model('username')).sendKeys(username);
element(by.model('password')).sendKeys(password);
element(by.buttonText('LOGIN')).click();
return this.waitForUrlToChangeTo(url);
}
And then in tests:
describe('when I login with valid credentials', function() {
it('should redirect to dashboard', function() {
helper.login('user', 'pass', '#/dashboard').then(function() {
expect(browser.getTitle()).toMatch('Dashboard');
});
});
});
I would say wait for logged in page until it displays properly and than do action. For e.g,
Target some element in logged-in page and wait for it.
Wait for url change, etc.
login -> browser.sleep(500)/wait for logged in page's element/URL change ->
other action
browser.driver.wait(function(){
expectedElement.isDisplayed().then(function (isVisible){
return isVisible === true;
},50000, 'Element not present ');
},50000);
if that element is not present within specified time, timeout error
would display & you would know unitl that time it's not logged in.

Can't retrieve anonymous authenticated user's info on first login

Logic: users select a few items on the homepage, then click a 'confirm' button which starts a Firebase $signInAnonymously() auth flow. Their selection is stored under their users/{uid} branch in the database tree and they are redirected to a checkout page that retrieves their selection and asks for more information to proceed.
Issue: when the user lands on the checkout page for the first time their auth state cannot be retrieved (so their selection doesn't appear). However when they refresh the page, everything works as expected for all subsequent attempts (their user info is stored and now retrievable)
Code:
User auth and selection setter/getter factory userService
var auth = $firebaseAuth();
var usersRef = $firebaseRef.users; // custom ref in app config
// Authenticate anonymously to create user session
function startSession() {
return auth.$signInAnonymously()
.then(function(user) {
return user;
})
.catch(function(error) {
console.log(error);
});
}
// Check authentication state before everything loads
function checkAuthState() {
return $q(function(resolve) {
var unsubscribe = auth.$onAuthStateChanged(function(user) {
if (user) {
unsubscribe();
resolve(user);
}
else {
console.log('User unidentified');
}
});
});
}
// Save user's menu selection into selection node of firebase
function saveSelection(items, user) {
var selectionRef = usersRef.child(user.uid).child('selection');
for (var i = 0, item; !!(item = items[i]); i++) {
var id = item.id;
if (item.selected) {
selectionRef.child(id).update(item);
}
else if (typeof(selectionRef.child(id)) !== 'undefined') {
selectionRef.child(id).remove();
}
}
}
// Get user's selection from firebase
function getSelection(user) {
var selectionRef = usersRef.child(user.uid).child('selection');
return $q(function(resolve) {
var selection = $firebaseArray(selectionRef);
resolve(selection);
});
}
Menu controller:
var menu = this;
menu.saveMenu = saveMenu;
// Save menu selection and create anonymous user on firebase
function saveMenu() {
var items = menu.items;
return userService.startSession()
.then(function(user) {
return userService.saveSelection(items, user);
});
}
Checkout controller:
// Get selected menu items from user data
function getCheckoutItems() {
return userService.checkAuthState()
.then(function(user) {
return userService.getSelection(user);
})
.then(function(selection) {
checkout.items = selection;
return checkout.items;
})
.catch(function(error) {
console.log(error);
});
}
I've looked through dozens of posts on SO before asking this. Here are a couple of the similar ones I've found:
Apparent race condition getting firebase.User from controller in Firebase 3.x
Handle asynchronous authentication in Firebase on page reload to get list that needs user's uid
I've also looked through the reference on GitHub to set it up:
https://github.com/firebase/angularfire/blob/master/docs/reference.md#firebaseauth
NB: I'm using the new version of Firebase with Angular 1.5.8:
"firebase": "^3.4.1",
"angularfire": "^2.0.2"
UPDATE
Got it. I had to add a resolve to my /checkout route to wait for authentication before loading elements on the page... Figured it out thanks to this answer by David East from the Firebase team.
resolve: {
// controller will not be loaded until $waitForSignIn resolves
"firebaseUser": function($firebaseAuthService) {
return $firebaseAuthService.$waitForSignIn();
}
}

how to redirect the page from controller according to condition in angularjs?

I have been working for authentication for each $http request and url changes. Therefore i have implemented peace of codes for url changing authentication as bellows
/** login-controller.js file **/
//when the form is submitted
$scope.submit = function() {
console.log("enter login submit");
$scope.submitted = true;
if (!$scope.loginForm.$invalid) {
$scope.login($scope.credentials);
} else {
$scope.error = true;
$scope.error_des = '';
return;
}
};
// if a session exists for current user (page was refreshed)
// log him in again
if ($window.sessionStorage["userInfo"]) {
var credentials = JSON.parse($window.sessionStorage["userInfo"]);
$scope.login(credentials);
};
//Performs the login function, by sending a request to the server with the Auth service
$scope.login = function(credentials) {
$scope.error = false;
Auth.login(credentials, function(user) {
//success function
$mdDialog.hide();
$state.go("admin-panel.default.home");
}, function(err) {
console.log("error");
$scope.error_des = err.msg;
$scope.error = true;
});
};
Everything is working as i expected but while reloding the same page it'l always redirect to home(http://localhost:3000/#/home).i know that it happens because of
$state.go("admin-panel.default.home");
trouble is , i want to redirect the page according to login way let'say if user login via form submitted which will be redirected to $state.go("admin-panel.default.home");
As well if user login via session exists for current user which will be redirected to $state.go("admin-panel.default."+$current_page);
how to achieve it? please help me????
If form submit : var formsubmitted = true;
if login via session : formsubmitted = false
and while routing you can check condition
if(formsubmitted == true)
$state.go("admin-panel.default.home");
else
$state.go("admin-panel.default."+$current_page);
//to get current page path you can use $location.path();

Delaying template rendering for authentication check in Angular

Angular can cause a big security issue if you have static URL's that lead to content in conjunction with an authentication scheme. If an unregistered user visits the page, the content will flash on screen for a moment before redirecting to a safe location. I found this issue, searched extensively, and settled upon the resolve property in $routeConfig. Unfortunately, no matter what I do, it doesn't work. Code below:
$routeProvider.when('/dashboard/:id', {
templateUrl: 'js/partials/dashboard.html',
controller:'DashCtrl',
access: access.user,
resolve: {
login: function(authService) {
var promise = authService.isLoggedIn();
promise.then(function(data){
// We're in successfully
}).catch(function(err){
// ew, go away, redirect to login page
window.location = "login";
});
}
}
});
AuthService.isLoggedIn() looks like:
isLoggedin : function() {
return $http.get("users/session_check").then(function(result) {
if (result.data) {
if (user == undefined)
{
placeholderService.populatePlaceholders();
user = result.data;
}
return result.data;
} else {
return $q.reject("Please log in.");
}
});
}
No matter what, the view flashes. I have ng-cloaks on the page, nothing. I have no idea what else to do, but this has become downright infuriating.
The function that you pass to $routeProvider should return a promise. e.g.:
$routeProvider.when('/dashboard/:id', {
templateUrl: 'js/partials/dashboard.html',
controller:'DashCtrl',
access: access.user,
resolve: {
login: function(authService) {
var promise = authService.isLoggedIn();
return promise.then(function(data){
// We're in successfully
return data; // This gets injected as "login"
}).catch(function(err){
// ew, go away, redirect to login page
window.location = "login";
});
}
}
});
And, if I recall correctly, the value that the promise is fulfolled with ends up being inject-able into the controller as a service (in this case, the login service is whatever your promise gets fulfilled with).

Resources