Using $scope in AngularJS to change value at index.html in routing - angularjs

I'm making a single page app in AngularJS using Firebase and using the side nav bar on index.html.
And after login, I want the username should be on the side nav bar but the $scope is working for the current page on the controller is working.
scotchApp.controller('mainController', function($scope) {
$scope.validateLogin = function()
{
var email = $scope.login.userName + "#xyz.co";
var password = $scope.login.password;
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
$scope.message = "please enter the correct details";
});
firebase.auth().onAuthStateChanged(function(user)
{
if(user)
{
$scope.usermobile = $scope.login.userName;
window.location.assign("/#/equipment");
}
});
}
$scope.message = '';
});

The current user is available in firebase.auth().currentUser as described in the docs so in your mainController you don't need to listen for auth changes.
In your code you are attaching a new listener each time the user tries to login, but what you actually want is to respond to one successful login, so just add a then to your sign in call:
firebase.auth().signInWithEmailAndPassword(email, password)
.then(function (user) {
console.log('the logged in user: ', user);
// Go to the other route here.
// It is recommended to use the router instead of "manually" changing `window.location`
})
.catch(function(error) {
$scope.message = "please enter the correct details";
});

Related

Handling secure login page in protractor

My team is working to use AngularJs and Polymer components for a new web app. I am looking into how to create a UI automation suite for this. After lots of research looks like Protractor may help me out here with some tweaks to handle Polymer. But, the current challenge is as follows -
I navigate to the app
As part of our company policy, the every web visit is validated (unless within same session). Here is how the validation works -
A login page (non-Anugular) page appears after one types the required url. Sign in with the credentials
Another intermediate page appears where it asks to wait for page to load or click a link to go to next page. Click the link
Url changes back to the original used in #1
Note: These validation pages take hell lot of time to load (changes to different internal urls). Also, the validation is skipped sometimes (within same session or through some other logic)
I have been struggling to design a prototype to handle all these. I am also trying to use Page Object while designing the prototype. Here is what I have so far.
login.js
________________________________________________________
var currentUrl;
var lastChangedUrl;
var secureUrl = 'corplogin.ssogen2.corporate.company.com';
var getwayUrl = 'gateway.zscalertwo.net';
var loginSuite = function(driver) {
var defer = protractor.promise.defer();
describe('Handle login', function() {
/*afterEach(function() {
//driver.manage().deleteAllCookies();
})*/
//it('Login to security test', function(){
//********** Wait for page to load/URL to change to secure login page ************
driver.getCurrentUrl().then(function(url) {
currentUrl = url;
}).then(function() {
driver.wait(function() {
return driver.getCurrentUrl().then(function (url) {
lastChangedUrl = url;
return url !== currentUrl;
});
});
}).then(function() {
//********** login to secure page ************
if (lastChangedUrl.indexOf(secureUrl) > -1 || lastChangedUrl.indexOf(getwayUrl) > -1) {
var element = driver.findElement(By.name("username"));
element.sendKeys("Username");
element = driver.findElement(By.name("password"));
element.sendKeys("password"); //Give password
element = driver.findElement(By.name("submitFrm"));
element.click();
}
}).then (function() {
//********** page is slow. wait for page to load/URL to change ************
driver.getCurrentUrl().then(function(url) {
currentUrl = url;
}).then(function() {
driver.wait(function() {
return driver.getCurrentUrl().then(function (url) {
lastChangedUrl = url;
return url !== currentUrl;
});
});
}).then (function() {
//********** Click on the link to to go to test page ***********
if (lastChangedUrl.indexOf(getwayUrl) > -1) {
var element = driver.findElement(By.tagName("a"));
console.log("before click............");
element.click();
}
//********** page is slow. wait for page to load/URL to change ************
driver.getCurrentUrl().then(function(url) {
currentUrl = url;
}).then(function() {
driver.wait(function() {
return driver.getCurrentUrl().then(function (url) {
lastChangedUrl = url;
return url !== currentUrl;
});
});
})
.then (function() {
//return defer.promise;
//browser.pause();
});
}, 60000);
});
//});
}, 60000);
return defer.promise;
};
module.exports = loginSuite;
spec.js
___________________________________________________________________________
describe('Protractor Demo App', function() {
var myUrl = 'http://<my test app url>/';
var driver = browser.driver;
beforeEach(function() {
driver.get(myUrl);
});
it('should login', function() {
loginSuite(driver)
.then(
function(){
console.log("End of tests:");
expect(driver.getCurrentUrl()).toBe(myUrl);
});
});
The issue here -
My expectation here is to have the promise returns to spec.js after the secure login page is handled so that I can continue with other testing using the driver object. For the sake testing I am logging 'End of tests' message and doing a dummy validation. But, looks like those two lines don't get executed.
Login to the secure site works and I see page changes to original test page. I tested that with Browser.pause(). But, the logging 'End of test' never happens, nor the validation.
I need to handle the scenario where the secure login page doesn't appear. Not sure what adjustment I need to do in login.js page
Is my approach for page object and handling the promises wrong here? I am able to go to one step further on the test app page when all the code are placed under one js file instead of splitting them for page object. Please help here.
I wanted to share with you the "polymer way" of solving your problem.
The code below use two elements to monitor the URL, the auth flow, the previous page visited and log the user in/out of the app
The first will bind to the origin route, so you can send the user back there
<app-route
route="{{route}}"
pattern="/origin/:page"
data="{{data}}"
tail="{{subroute}}">
</app-route>
The second will bind to the authPage, allowing you to show/hide the auth page.
<app-route
route="{{subroute}}"
pattern=":authPage"
data="{{data}}
active="{{authPageActive}}">
</app-route>
User auth, monitoring and page redirecting
Use the element: <firebase-auth>
Is the user singned in?: signedIn="{{isSignedIn}}"
<firebase-auth id="auth" user="{{user}}" provider="google" on-
error="handleError" signedIn="{{isSignedIn}}"></firebase-auth>
Add an observer
observers: [
'_userSignedInStatus(isSignedIn)' // observe the user in/out
],
Add a Function
_userSignedInStatus: function (isSignedIn) {
if (isSignedIn === false) {
this.page = 'view404'; // redirect the user to another page
// import an element that cover the view
} else {
//send a log message to your database
}
}

On Auth State changed AngularFire

Trying to authenticate an user using firebase. Started my app using firebase 2.xx but even after upgrading to Firebase 3.xx, throwing
error "onAuthStateChanged is not a function".
This is how my login function looks like-
.controller('HomeCtrl', ['$scope','$location','CommonProp','$firebaseAuth', '$firebaseObject',function($scope,$location,CommonProp,$firebaseAuth,$firebaseObject) {
var firebaseObj = $firebaseObject(rootRef);
var loginObj = $firebaseAuth(firebaseObj);
$scope.SignIn = function($scope, user) {
event.preventDefault(); // To prevent form refresh
var username = user.email;
var password = user.password;
loginObj.$signInWithEmailAndPassword({
email: username,
password: password
})
.then(function(user) {
// Success callback
console.log('Authentication successful');
$location.path("/welcome");
CommonProp.setUser(user.password.email);
}, function(error) {
// Failure callback
console.log(error);
});
}
}]);
Your problem is that you are passing a $firebaseObject to $firebaseAuth().
So make sure you are initializing your [$firebaseAuth][1] object like the following and then your code should work properly.
var loginObj = $firebaseAuth();
Working jsFiddle for demonstrating.
You can check here the documentation for AngularFire2

How to prevent new anonymous authentication UID after browser refresh in Firebase

I am using anonymous authentication in Firebase with Angular. The goal is to have one UID associated with a user until the browser is closed. I would like to use the same UID even if the page is refreshed. However, when I use the code below, a new UID and token is created every time a user refreshes the page. How do I prevent this from happening?
myApp.factory('fbAuth', function($firebaseAuth) {
var ref = new Firebase('https://xxxxxxxx.firebaseio.com');
ref.authAnonymously(function (error, authData) {
if (error) {
console.log('Login Failed!', error);
} else {
console.log('Authenticated successfully with payload:', authData);
}
},
{remember: 'sessionOnly'
});
});
myApp.controller('ProjectListCtrl', function(Projects, fbAuth) {
var projectList = this;
projectList.projects = Projects;
});

AngularJS does not update after value change

My intention is to update the navigation bar after the user login. Basically, it should change Login to Hi, {{usr.username}} right after the login.
However, it does not update after logging in and I have to click on Login again to trigger the change. However, in the console, the user info is logged right after the login.
In the index.html, the part of the code looks like:
<div class="item" ng-click="loginmodal()" ng-hide="loggedIn">Log in</div>
<div class="item" ng-show="loggedIn">Hi, {{usr.username}}</div>
where $scope.loggedIn is initialized as false and $scope.usr as null. I am using firebase for authentication:
FirebaseRef.authWithPassword({
"email" : email,
"password" : password
}, function(error, authData) {
if (error) {
console.log('Login Failed!', error);
} else {
console.log('Authenticated successfully with payload:', authData);
FirebaseRef.child("users").child(authData.uid).once('value', function(dataSnapshot) {
$scope.usr = dataSnapshot.val();
});
$scope.loggedIn = true;
console.log($scope.usr);
console.log($scope.loggedIn);
}
});
In console, I have $scope.loggedIn as true, but have $scope.usras null.
Is it wrong how I am using the authWithPassword() function or can I force the change to be updated?
AngularJS won't update the view if any changes to the $scope object are done outside of its $digest loop.
But worry not, Firebase is such a popular tool it has a AngularJS service. It's called AngularFire and you should be using it instead of global Firebase object.
So your code will be something similar to:
var auth = $firebaseAuth(FirebaseRef);
auth.$authWithPassword({
email: email,
password: password
}).then(function (authData) {
console.log('Authenticated successfully with payload:', authData);
var sync = $firebase(FirebaseRef.child("users").child(authData.uid));
var syncObject = sync.$asObject();
syncObject.$bindTo($scope, "usr");
}).catch(function (error) {
console.error('Login Failed!', error);
});
Read more in the documentation of AngularFire
Try calling $scope.$digest() right after changing $scope.usr value.
Anyway, notice that you call to Firebase to get the user is asynchronous, so I wouldn't put dependent code after this call, but inside the callback.
Call $scope.$apply();
FirebaseRef.child("users").child(authData.uid).once('value', function(dataSnapshot) {
$scope.$apply(function(){
$scope.usr = dataSnapshot.val();
});
});

Angular rendering engine & Firebase profile retrieval

What I want:
firebase checks authentication of page load
firebase returns userID if logged in
my function returns the username associated with the user.Id
assign to the variable that represents the username
render!
All on page load
Current Behavior:
The following configuration retrieves the username but will only display the username once I click a login button I have made.For some reason even though I am currently logged in I must click the login button. I want a set up where if I am logged in the app will just know I am logged in from the start!
crossfitApp.controller('globalIdCtrl', ["$scope",'$q','defautProfileData','$timeout', function ($scope,$q,defautProfileData,$timeout) {
var dataRef = new Firebase("https://glowing-fire-5401.firebaseIO.com");
$scope.myFbvar =null;
$scope.authenticated={
currentUser: null,
avatarUrl: "",
emailAddress: "",
settings: "",
currentUserid: null,
};
function getProfile(userID,assignMe){
myprofile= new Firebase("https://glowing-fire-5401.firebaseio.com/profiles/"+userID+"/username");
myprofile.once('value', function(nameSnapshot) {
assignMe = nameSnapshot.val();
});
};
$scope.auth = new FirebaseSimpleLogin(dataRef, function(error, user) {
if (error) {
//Error
console.log ('error');
}
else if (user) {
//logged in
$timeout(function() {
getProfile(user.id,);
});
console.log('logged in');
$scope.authenticated.currentUserid = user.id ;
}
else {
// user is logged out
console.log('logged out');
$timeout(function() {
$scope.authenticated.currentUserid =null;
});
}
});
}]); //Global
In your else if( user ) logic, you forgot to put your scope var inside the $timeout, so it is being set properly, but Angular doesn't learn about it until the next time $apply is called (e.g. ng-click, ng-submit, etc).
Thus:
else if (user) {
//logged in
$timeout(function() {
getProfile(user.id,);
$scope.authenticated.currentUserid = user.id ; // moved into $timeout
});
console.log('logged in');
}
You can read more about why this matters here and here.

Resources