ng-show attribut causes html block blinking (beginner) - angularjs

On my login page, when I enter wrong credentials (login/pass), an error message is displayed in red.
In login.html :
<div class="alert alert-danger" ng-show="authenticationError"
translate="login.messages.error.authentication">
<strong></strong>
</div>
If I set ng-show="true" explicitely, The message is persistent on the screen ; (fortunately).
The problem comes when ng-show is dynamic (with authenticationError variable)
When this variable is set to true, then the error message appears but left 1 second on the screen and then disappear.
Behind the scene (controller + service) :
login.controller.js :
$scope.login = function () {
// event.preventDefault();
Auth.login({
username: $scope.username,
password: $scope.password,
rememberMe: $scope.rememberMe
}).then(function () {
$scope.authenticationError = false;
// if()
if ($rootScope.previousStateName === 'register') {
$state.go('home');
} else {
$rootScope.back();
}
}).catch(function () {
$scope.authenticationError = true;
});
};
auth.service.js :
angular.module('tessicommunicationApp')
.factory('Auth', function Auth($rootScope, $state, $q, $translate, Principal, AuthServerProvider, Account, Register, Activate, Password, PasswordResetInit, PasswordResetFinish) {
return {
login: function (credentials, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();
console.log("login ...");
AuthServerProvider.login(credentials).then(function (data) {
// retrieve the logged account information
Principal.identity(true).then(function(account) {
// After the login the language will be changed to
// the language selected by the user during his registration
$translate.use(account.langKey).then(function(){
$translate.refresh();
});
deferred.resolve(data);
});
return cb();
}).catch(function (err) {
this.logout();
deferred.reject(err);
console.log("erreur login !");
return cb(err);
}.bind(this));
return deferred.promise;
},
auth.session.service.js :
angular
.module('tessicommunicationApp')
.factory(
'AuthServerProvider',
function loginService($http, localStorageService, $window, $state, $cookies) {
return {
login : function(credentials) {
var data = 'j_username='
+ encodeURIComponent(credentials.username)
+ '&j_password='
+ encodeURIComponent(credentials.password)
+ '&remember-me=' + credentials.rememberMe
+ '&submit=Login';
return $http
.post(
'api/authentication',
data,
{
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
}).success(function(response) {
return response;
});
},
Tell me if you need more code.
The context is :
1) I need to debug this ticket.
2) I didn't code anything of this web application (especially front-end part)
3) I almost have NO knowledges in AngularJS (just theory a little).
I wish you will help me to solve my first ticket :).*

Aren't you missing a parenthesis and extra parenthesis at the end of the statement here:
}).catch(function (err) {
this.logout();
deferred.reject(err);
console.log("erreur login !");
return cb(err);
}.bind(this));// <-- missing parenthesis
It should be like:
}).catch(function (err) {
this.logout();
deferred.reject(err);
console.log("erreur login !");
return cb(err);
}).bind(this);
Something else you can try when suspect about changes occurring without you know is monitoring the variable change with a $watch like:
$scope.countChange = 0;
$scope.$watch('authenticationError', function(newValue, oldValue) {
$scope.countChange = $scope.countChange + 1;
console.log('Change count :',$scope.countChange , ' New Value =', newValue );
});

Related

AngularJs block ulr navigation when user is not logged in

I have to allow user to access application when user is logged in
and if user is not logged in then user should not be able to access the application by simply redirecting through url
In above case user should redirect to login page if he is not logged in
I tried in below way
$rootScope.tempObj = false;
$rootScope.$on('$stateChangeStart', function (event, toState) {
if($rootScope.tempObj) {
return;
} else {
$state.go('login');
event.preventDefault();
return;
}
});
Here i am doing $rootScope.tempObj = true in login success callback
But I am getting an error - RangeError: Maximum call stack size exceeded
My question is how to block url redirection if user is not logged in..
and allow few state like forgot password, reset password, etc without user logged in
use it with the event.preventDefault();
$rootScope.$on('$stateChangeStart', function(event, toState) {
if ($rootScope.tempObj) {
event.preventDefault();
} else if (!$rootScope.tempObj) {
$state.go('login');
event.preventDefault();
}
});
check the similar question
i think this way isn't perfect way to check user, if your application deals with backend by sending http requests you should test user privileges from $httpProvider, so in $httpProvider if you get a http code in 400 range, you should redirect user to login page,
i'll put a snipping code to do this
.config(["$httpProvider", "$cookiesProvider", function($httpProvider, $cookiesProvider) {
$cookiesProvider.defaults.expires = new Date(new Date().getTime() + 120 * 60 * 1000).toString();
// $httpProvider.defaults.timeout = 50;
var interceptor = function($q, $rootScope, $injector, $location, $filter) {
return {
request: function(config) {
return config;
},
requestError: function(config) {
return config;
},
response: function(res) {
return res;
},
responseError: function(res) {
var AUTH_EVENTS = $injector.get('AUTH_EVENTS');
var $toastContent = $('<span>' + $filter('translate')(res.data.message) + '</span>');
if (res.status == 403) {
$location.path('/logOut');
}
if (res.status == 402) {
$location.path('/home');
Materialize.toast($toastContent, 4000, 'danger');
}
if (res.status == 401) {
Materialize.toast($toastContent, 4000, 'danger');
}
// }
return $q.reject(res);
}
}
}
interceptor.$inject = ["$q", "$rootScope", "$injector", "$location", "$filter"];
$httpProvider.interceptors.push(interceptor);
}])

whats wrong in this $http request in angular?

Here is the code :
(function () {
angular.module('PillApp').factory('AuthFactory',
['$q', '$timeout', '$http', 'Flash', '$state',
function ($q, $timeout, $http, Flash, $state) {
// create user variable
var user = null;
// return available functions for use in the controllers
return ({
isLoggedIn: isLoggedIn,
getUserStatus: getUserStatus,
login: login,
logout: logout,
register: register
});
function isLoggedIn() {
if(user) {
return true;
} else {
return false;
}
}
function getUserStatus(callback) {
$http.get('/status/user')
// handle success
.then(function (data) {
//console.log(JSON.stringify(data));
if(data.data !== ''){
user = true;
callback(user);
} else {
user = false;
callback(user);
}
});
}
function login(userProfile) {
// create a new instance of deferred
var deferred = $q.defer();
console.log("Authentication Service - to send login to server");
// send a post request to the server
$http.post('/login',
userProfile)
// handle success
.success(function (data, status) {
console.log("Authentication response received");
if(status == 200){
getUserStatus(function(result){
if(result){
deferred.resolve();
$state.go('A');
}else{
deferred.reject();
Flash.create('danger', "Ooops having issue logging in!", 0, {class: 'custom-class', id: 'custom-id'}, true);
$state.go('A');
}
});
} else {
user = false;
Flash.clear();
Flash.create('danger', "Ooops having issue logging in!", 0, {class: 'custom-class', id: 'custom-id'}, true);
deferred.reject();
}
})
// handle error
.error(function (data) {
console.log("Authentication error - any flash messsage?");
user = false;
Flash.clear();
Flash.create('danger', "Ooops having issue logging in!", 0, {class: 'custom-class', id: 'custom-id'}, true);
deferred.reject();
});
// return promise object
return deferred.promise;
}
function logout() {
// create a new instance of deferred
var deferred = $q.defer();
// send a get request to the server
$http.get('/logout')
// handle success
.success(function (data) {
user = false;
deferred.resolve();
})
// handle error
.error(function (data) {
user = false;
deferred.reject();
});
// return promise object
return deferred.promise;
}
function register(username, password) {
// create a new instance of deferred
var deferred = $q.defer();
console.log("Sending registration to server");
// send a post request to the server
$http.post('/register',
{username: username, password: password})
// handle success
.success(function (data, status) {
if(status){
console.log('Registration successful', data, status);
deferred.resolve();
} else {
console.log('Registration unsuccessful', data);
Flash.closeFlash();
Flash.create('danger', "Can't register with us!", 0, {class: 'custom-class', id: 'custom-id'}, true);
deferred.reject();
}
})
// handle error
.error(function (data) {
console.log('Registration error', data);
Flash.clear();
Flash.create('danger', "Ooops something went wrong!", 0, {class: 'custom-class', id: 'custom-id'}, true);
deferred.reject();
});
// return promise object
return deferred.promise;
}
}]);
})();
ERROR :
angular.js:14324 TypeError: $http.post(...).then is not a function
at Object.login (http://ec2-52-77-252-229.ap-southeast-1.compute.amazonaws.com:3001/services/auth.factory.js:55:22)
at AppCtrl.vm.login (http://ec2-52-77-252-229.ap-southeast-1.compute.amazonaws.com:3001/app.controller.js:35:25)
at fn (eval at compile (http://ec2-52-77-252-229.ap-southeast-1.compute.amazonaws.com:3001/bower_components/angular/angular.min.js:236:285), <anonymous>:4:167)
at e (http://ec2-52-77-252-229.ap-southeast-1.compute.amazonaws.com:3001/bower_components/angular/angular.min.js:281:195)
I tried $http.post().success also and it gives error like success is not defined
Than i tried $http.post().then also and it gives error like then is not defined
I have injected $http in a right way.it worked on localhost but during production it gives this kind of errors.
You need to define functions containing http post directive in this manner :
$scope.getUserCallback = function (callback) {
$http.get('/status/user')
// handle success
.then(function (data) {
//console.log(JSON.stringify(data));
if(data.data !== ''){
user = true;
callback(user);
} else {
user = false;
callback(user);
}
});
};
then you can call it from inside the script wherever required as
$scope.getUserCallback();
and from an html element like this
<my element ng-click="getUserCallback()"></my element>
I think the $http.post call is failing due to CORS. You may need to enable CORS or send the appropriate HTTP headers in your request. The error you are getting because the $http.post is not returning the expected object which can execute the next success or then methods.
It would work correctly on your localhost as there is no CORS restriction in local development environment.

FB.logout Issue, FB.getLoginStatus() returning unknown status

I am trying to get the FB.logout() functionality working.
Then error I get is FB.logout() called without an access token.
so I googled around to find some solutions. So I found that we have to get the status and try then. So when I try to getLoginStatus(). the authResponse is Null, status is unknown.
So I don't know what's the reason that I am not getting the authResponse.
I am attaching my code.
Controller.js
app.controller("dashboardCtrl",["$scope","authFactory","$location",function($scope,authFactory,$location){
var userObj = authFactory.getUserObj(userObj);
console.log(userObj);
var accessToken = authFactory.getAccessToken();
console.log(accessToken);
$scope.accessToken = accessToken;
$scope.FBout = function(){
FB.getLoginStatus(function(response) {
console.log(response);
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
FB.logout(function(response) {
authFactory.clearCookie();
});
} else if (response.status === 'not_authorized') {
} else {
}
});
};
}]);
factory.js
app.factory("authFactory",["$cookies","$location",function($cookies,$location){
var authFactory = {};
authFactory.setAccessToken = function(accessToken){
$cookies.put("accessToken",accessToken);
}
authFactory.getAccessToken = function(){
return $cookies.get("accessToken");
}
authFactory.getUserObj = function(){
var userObj = $cookies.get('userObj');
if(userObj){
return userObj;
}
else {
console.log("error");
}
}
authFactory.clearCookie = function(){
$cookies.remove("accessToken");
$location.path("/")
}
return authFactory;
}]);
I am not able to logout and redirect to someother page. I am stuck, I have accesstoken, and user object in the cookie.
I am sure I have unchecked the thirdparty app access thing in chrome settings.
Updating with another controller where I logged in, which might be required.
app.controller('homeCtrl',["$scope","authFactory","$location","$cookieStore",function($scope,authFactory,$location,$cookieStore){
$scope.name = "login Please";
$scope.FBLogin = function(){
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
$cookieStore.put("userObj",response);
var accessToken = FB.getAuthResponse().accessToken;
authFactory.setAccessToken(accessToken);
$location.path("/dashboard");
$scope.$apply();
});
} else {
console.log('User cancelled login or did not fully authorize.');
}
});
};
}]);
this is my Route.js
app.config(["$routeProvider",function($routeProvider){
$routeProvider
.when("/",{
templateUrl : 'views/home/login.html',
controller : 'homeCtrl'
})
.when("/dashboard",{
templateUrl : 'views/home/dashboard.html',
controller : 'dashboardCtrl',
authenticated : true
})
.otherwise('/',{
templateUrl : 'views/home/login.html',
controller : 'homeCtrl'
})
}]);
app.run(["$rootScope","$location","authFactory",function($rootScope,$location,authFactory){
$rootScope.$on('$routeChangeStart',function(event,next,current){
if(next.$$route.authenticated){
var userAuth = authFactory.getAccessToken();
if(!userAuth){
$location.path('/');
}
}
});
}]);
Try to disable caching in FB.getLoginStatus:
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
FB.logout(function(response) {
authFactory.clearCookie();
});
}
}, true);
More information: https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus#servers
I had the same problem, try this one:
FB.api(
'/me/permissions',
'DELETE',
{},
function(response) {
// Here fb should remove the token.
// response should be "success: true"
FB.logout(() => {
// Here logout.
});
}
);

Check if a user has isAdmin true

I'm trying to make an isAdmin() function that will check if the current user has "isAdmin: true" in the mongodb.
server.js
app.get('/api/isadmin', function (req, res) {
User.findById(req.user, function (err, user) {
if (req.user.isAdmin == true) {
res.send(user);
} else {
return res.status(400).send({ message: 'User is not Admin' });
}
});
});
AdminCtrl.js
angular.module('App')
.controller('AdminCtrl', function ($scope, $http, $auth) {
$http.get('http://localhost:3000/api/isadmin')
.then(function (res) {
$scope.isAdmin = res.data;
}
});
when I access the page /admin it throws "cannot read property 'isAdmin' of null" in the if inside app.get. Why is this occuring, and what is the optimal way for me to make this isAdmin function?
You are not using the variable sent back to you, but still the req.
app.get('/api/isadmin', function (req, res) {
User.findById(req.user, function (err, user) {
if (user.isAdmin == true) {
res.send(user);
} else {
return res.status(400).send({ message: 'User is not Admin' });
}
});
});
Maybe this should work (assuming you are returned if the user isAdmin)
try following
angular.module('App')
.controller('AdminCtrl',['$scope','$http','$auth', function ($scope, $http, $auth) {
$http.get('http://localhost:3000/api/isadmin')
.then(function (res) {
$scope.isAdmin = res.data;
}
}]);

How should you getCurrentUser after a page reload?

Here is how I'm doing it so far:
angular
.module('mean-starter')
.factory('Auth', function($http, $state, $window, $cookies) {
var currentUser = {};
return {
signup: function(user) {
return $http
.post('/users', user)
.then(function(data, status, headers, config) {
angular.copy(data, currentUser);
$cookies.put('userId', data._id);
$window.location.href = '/';
})
;
},
login: function(user) {
return $http
.post('/login', user)
.then(function(data) {
angular.copy(data, currentUser);
$cookies.put('userId', data._id);
$window.location.href = '/';
})
;
},
logout: function() {
$http
.get('/logout')
.then(function() {
angular.copy({}, currentUser);
$cookies.remove('userId');
$window.location.href = '/';
})
.catch(function() {
console.log('Problem logging out.');
})
;
},
getCurrentUser: function() {
// user is logged in
if (currentUser._id) {
return currentUser;
}
// user is logged in, but page has been refreshed and currentUser is lost
if ($cookies.get('userId')) {
return $http.get('/current-user')
.then(function(data) {
angular.copy(data, currentUser);
})
;
}
// user isn't logged in
else {
return currentUser;
}
},
isLoggedIn: function() {
return !!currentUser._id;
}
};
})
;
After a page reload, the Auth factory gets re-run and currentUser is reassigned to {}. So if the user was logged in, currentUser won't reflect it. So I have to check for the case where !currentUser._id && $cookies.get('userId') and if so, query the database for the currently logged in user.
Now I want to access currentUser:
angular
.module('mean-starter')
.run(run)
;
function run($rootScope, Auth, $state) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams) {
if (typeof toState.authenticate !== 'undefined') {
var currentUser = Auth.getCurrentUser();
var admin = currentUser.role === 'admin';
var authorized = currentUser._id.toString() === toParams.id;
if (!Auth.isLoggedIn()) {
event.preventDefault();
alert('Must be logged in to access this route.');
$state.go('login');
}
else if (toState.authenticate.authorized) {
if (!admin && !authorized) {
event.preventDefault();
alert('You are not authorized to access that route.');
}
}
else if (toState.authenticate.isAdmin) {
if (!admin) {
event.preventDefault();
alert('You must be an admin to access this route.');
}
}
}
});
}
The problem is that I don't know whether or not Auth.getCurrentUser() will return the user or a promise. How can I check for this? How should this be architected?
Why not just always return a promise in your getCurrentUser with the help of $q?
So something like this
getCurrentUser: function() {
if (currentUser._id || !$cookies.get('userId')) {
// $q.when will wrap your currentUser into a promise
return $q.when(currentUser);
}
return $http.get('/current-user')
.then(function(data) {
angular.copy(data, currentUser);
return currentUser;
});
}
}
and in your controller:
Auth.getCurrentUser().then(function(currentUser) {
// Your code
})
You can adapt your function to return a promise in both cases using $q. In this case, all three logical paths should result in the same outcome, albeit by different sets of operations in between, therefore a promise would work perfectly here. Especially because you can have very specific control over the error handling flow (if needed)
http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/

Resources