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;
}
}]);
Related
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 );
});
I can catch the profile information of a Facebook account like this:
var facebookExample = angular.module('starter', ['ionic', 'ngStorage', 'ngCordova'])
facebookExample.controller("ProfileController", function($scope, $http, $localStorage, $location) {
$scope.init = function() {
if($localStorage.hasOwnProperty("accessToken") === true) {
$http.get("https://graph.facebook.com/v2.2/me", { params: { access_token: $localStorage.accessToken, fields: "id,name,gender,location,website,picture,relationship_status", format: "json" }}).then(function(result) {
$scope.profileData = result.data;
}, function(error) {
alert("There was a problem getting your profile. Check the logs for details.");
console.log(error);
});
} else {
alert("Not signed in");
$location.path("/login");
}
};
});
Now, I am trying to catch the information of an Facebook event with this:
facebookExample.controller("EventController", function($scope, $http, $localStorage, $location) {
$scope.init = function() {
if($localStorage.hasOwnProperty("accessToken") === true) {
$http.get("https://graph.facebook.com/v2.2/{event-id}", { params: { access_token: $localStorage.accessToken, fields: "id, name, cover, place, description", format: "json" }}).then(function(result) {
$scope.eventData = result.data;
}, function(error) {
alert("There was a problem getting your profile. Check the logs for details.");
console.log(error);
});
} else {
alert("Not signed in");
$location.path("/login");
}
};
});
but my eventData returns empty... I am building an ionic app with cordova and angular. Anyone can help?
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/
I am trying to implement a persistent login for an angular application. By persistent I mean I am able to redirect to a new page or refresh without being logged out.
Looking at the debugger it does not appear that my /api/users route is ever being hit. api/sessions is and im not sure why the other one wouldn't be.
my code is:
routes.js
app.post('/api/sessions', function(req, res, next) {
User.findOne({username: req.body.username})
.select('password').select('username')
.exec( function(err, user){
if (err) {return next(err)}
if (!user) {return res.send(401)}
bcrypt.compare(req.body.password, user.password, function (err, valid){
if (err) {return next(err)}
if (!valid) {return res.send(401)}
var token = jwt.encode({username: user.username}, config.secret)
res.send(token)
})
})
})
app.get('/api/users', function(req, res, next) {
if(!req.headers['x-auth']){
return res.send(401)
}
var auth = jwt.decode(req.headers['x-auth'], config.secret)
User.findOne({username: auth.username}, function (err,user){
if (err) {return next(err)}
res.json(user)
})
})
app.post('/api/users', function(req, res, next) {
var user = new User({username: req.body.username})
bcrypt.hash(req.body.password, 10, function (err, hash){
if (err) {return next (err)}
user.password = hash
user.save(function (err){
res.send(201)
})
})
})
angular.js
app.service('UserSvc', function($http, $window){
var svc = this;
svc.getUser = function() {
return $http.get('/api/users',{
headers: { 'X-Auth': this.token }
})
}
svc.login = function(username, password){
return $http.post('/api/sessions', {
username: username, password: password
}).then(function(val){
svc.token = val.data
// window.localStorage.token = val.data
return svc.getUser()
})
}
svc.logout = function() {
$http.post('/api/sessions', {
username: null, password: null
}).then(function(val){
svc.token = null
// window.localStorage.token = val.data
})
}
})
app.controller('LoginCtrl', function($scope, $location, UserSvc){
$scope.login = function(username, password) {
UserSvc.login(username, password)
.then(function(response) {
$scope.$emit('login', response.data)
$location.path('/dashboard');
})
}
$scope.logout = function() {
UserSvc.logout();
$scope.$emit('logout')
}
});
app.controller('ApplicationCtrl', function($scope, UserSvc) {
angular.element(document).ready(function () {
$scope.currentUser = UserSvc.getUser();
})
$scope.modalShown = true;
$scope.$on('login', function (_, user){
$scope.currentUser = user;
})
$scope.$on('logout', function (){
$scope.currentUser = null;
})
});
if anyone has any pointers please let me know! I have spent way to much time on this :(
I believe the problem is rather simple here.
Services need to be instantiated (with new UserSvc).
Factories do not. So if you wanted it to use it the way you are, change UserSvc to be a factory and have it return svc.
Other thing to note would be that Factories/Services are singletons, so returning the svc, along with a variable holding the resultant user object will persist through angular router traversal but not on a page refresh. For that you would want to store the user in sessionStorage on the client (or in localStorage with some sort of timeout).
I am using mongoose to create a user object on register. This works fine and any errors are returned as expected.
However, I want to log the user on right after they register (so registering logs you on if there are no errors).
I have the following for the register.
register_controller:
$scope.submitRegister = function() {
AuthenticationService.register(this.details).success(function() {
$log.debug('/POST to /api/register worked');
});
}
services.js:
.service('AuthenticationService', function($http, $timeout, $q, $session, $flash) {
...
this.register = function(details) {
var register = $http.post('/api/register', details);
register.success(function() {
console.log("User added fine");
}).error(function() {
console.log("error!!!");
});
return register;
};
...
users.js:
app.post('/api/register', authentication.register);
passport's authenticate.js:
module.exports = {
...
register: function(req, res){
var User = require('./controllers/api/login_api');
User.create({name: req.body.name, email: req.body.email, password: req.body.password}, function(err){
if (err) {
console.log(err);
return;
}
console.log("User added");
return res.send(200);
});
},
...
The error is reported back fine, no troubles, but I would have thought it would report something else back (like the created object?) which I could use down the line so my register_controller can have in the success function(object) {... login(object);...}.
Is this a limitation in the .create method or am I missing something obvious?
Thank you.
Two things to change in your server code:
passport's authenticate.js:
module.exports = {
...
register: function(req, res){
var User = require('./controllers/api/login_api');
User.create({name: req.body.name, email: req.body.email, password: req.body.password}, function(err, user){
if (err) {
console.log(err);
return;
}
console.log("User added");
return res.send(200, user);
});
},
...
I've added user to your callback Mongoose model.create api - return the created object to the CB
And to change the catch in your client:
.service('AuthenticationService', function($http, $timeout, $q, $session, $flash) {
...
this.register = function(details) {
var register = $http.post('/api/register', details);
register.success(function(user) {
console.log(user);
}).error(function() {
console.log("error!!!");
});
return register;
};
...
Now you can do with the created user object whatever you need