I'm very confusing because of 'this' property.
What does "delete this.user;" mean in AuthenticationFactory. I think function "check" is a method so it will be bind with 'auth' object. But, there is no 'user' property in 'auth' Object. Can you explain it?
Also, in 'UserAuthFactory' (delete AuthenticationFactory.user, delete AuthenticationFactory.userRole)
I can't figure out what are "user" and "userRole" properties. There are no such properties in AuthenticationFactory.
Here the my code from http://thejackalofjavascript.com/architecting-a-restful-node-js-app/
myApp.factory('AuthenticationFactory', function($window) {
var auth = {
isLogged: false,
check: function() {
if ($window.sessionStorage.token && $window.sessionStorage.user) {
this.isLogged = true;
} else {
this.isLogged = false;
delete this.user;
}
}
}
return auth;
});
myApp.factory('UserAuthFactory', function($window, $location, $http, AuthenticationFactory) {
return {
login: function(username, password) {
return $http.post('http://localhost:3000/login', {
username: username,
password: password
});
},
logout: function() {
if (AuthenticationFactory.isLogged) {
AuthenticationFactory.isLogged = false;
delete AuthenticationFactory.user;
delete AuthenticationFactory.userRole;
delete $window.sessionStorage.token;
delete $window.sessionStorage.user;
delete $window.sessionStorage.userRole;
$location.path("/login");
}
}
}
});
If you look further down, to the controller code:
$scope.login = function() {
var username = $scope.user.username,
password = $scope.user.password;
if (username !== undefined && password !== undefined) {
UserAuthFactory.login(username, password).success(function(data) {
AuthenticationFactory.isLogged = true;
AuthenticationFactory.user = data.user.username;
AuthenticationFactory.userRole = data.user.role;
$window.sessionStorage.token = data.token;
$window.sessionStorage.user = data.user.username; // to fetch the user details on refresh
$window.sessionStorage.userRole = data.user.role; // to fetch the user details on refresh
$location.path("/");
}).error(function(status) {
alert('Oops something went wrong!');
});
} else {
alert('Invalid credentials');
}
};
On a successfully login, the controller is adding the properties user and userRole to the AuthenticationFactory.
Related
I have created login page and trying to do client-side authentication. I know it's a bad practice, but I want to learn it. I am accessing the data using JSON server. When I submit the button , my data is getting posted in the server, but I am failing when I am trying to match the content on success call. Please let me know what I am doing wrong.
Any help / advice would be greatly appreciated.
AngularJS :
app.factory('Authentication', function($http, $q, session) {
var service = {};
service.isAuthenticated = function() {
return isAuthenticated = false,
username = ""
};
service.login = function(username, password) {
return $q(function(resolve, reject) {
$http.post('http://localhost:3000/loginfo', {
username,
password
})
.then(
function successCallback(response) {
var data = response.data;
var user = {};
for (var i = 0; i < data; i++) {
alert('go');
if (data[i].username === username && data[i].password === password) {
user = data[i];
break;
}
}
session.create(response.data.id, response.data.username);
resolve(response.data);
console.log(response.data)
},
function(err) {
reject(err);
});
});
};
return service;
});
/* client-side */
app.controller('credientials', function($scope, $http, auth) {
$scope.userCred = {
username: '',
password: ''
};
/*-----Form Submition-----*/
$scope.log = function(userCred) {
$scope.isAuthenticated = true;
Authentication.login(userCred.username, userCred.password)
.then(function(result) {
console.log(result);
}, function(err) {
console.error(err);
});
};
}]);
Hi for some reason everytime i try to push data into my array i get a error returned saying the array is undefined
function getPosts(initial){
var data = {};
if ($scope.user){
data.ids = angular.copy($scope.user.friends);
data.ids.push($scope.user._id)
}
$http.post('api/social/getPost', data).success(function(response) {
if (initial) {
$scope.wallposts = response;
if (response.length == 0) {
getPosts(true);
} else {
$scope.wallposts = response;
}
} else {
if (response.length > $scope.wallposts.length) {
$scope.IncomingPosts = response;
}
}
});
};
this is the error
Error: data.ids is undefined
getPosts#http://localhost:3000/client/controllers/PostController.js:48:16
#http://localhost:3000/client/controllers/PostController.js:105:9
invoke#http://localhost:3000/node_modules/angular/angular.js:4604:16
$ControllerProvider/this.$get</</instantiate<#http://localhost:3000/node_modules/angular/angular.js:9855:24
nodeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8927:34
compositeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8226:13
compositeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8229:13
compositeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8229:13
compositeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8229:13
nodeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8973:1
compositeLinkFn#http://localhost:3000/node_modules/angular/angular.js:8226:13
publicLinkFn#http://localhost:3000/node_modules/angular/angular.js:8106:30
compilationGenerator/<#http://localhost:3000/node_modules/angular/angular.js:8447:20
createBoundTranscludeFn/boundTranscludeFn#http://localhost:3000/node_modules/angular/angular.js:8244:1
controllersBoundTransclude#http://localhost:3000/node_modules/angular/angular.js:9020:20
ngIfWatchAction#http://localhost:3000/node_modules/angular/angular.js:25059:15
$RootScopeProvider/this.$get</Scope.prototype.$digest#http://localhost:3000/node_modules/angular/angular.js:16664:23
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://localhost:3000/node_modules/angular/angular.js:16928:13
done#http://localhost:3000/node_modules/angular/angular.js:11266:36
completeRequest#http://localhost:3000/node_modules/angular/angular.js:11464:7
requestLoaded#http://localhost:3000/node_modules/angular/angular.js:11405:1
however if i remove the line that pushed the id into the array everything works fine?
the code on the server side is
module.exports.getPosts = function(req, res){
//get all friends and users posts
Posts.find( {postedBy: {$in: req.body.ids}} )
.sort({postedOn: -1})
.exec(function(err, allPosts){
if (err) {
console.log(err)
} else {
res.json(allPosts)
}
});
};
all i am trying to do is gather all ids from the users friend then add the users id to the array so i can use a $in query to search mongo for all posts that have been created by them ids.
i have spent 5 days on this bug and to be honest i have no idea what is going on
here is the full code for the client side in case it helps
(function(){
angular.module('Scrimbox')
.controller('postsController', ['$scope', '$http', '$interval', '$routeParams', function( $scope, $http, $interval, $routeParams){
$scope.newPost = function(){
var request = {};
var user = JSON.parse(localStorage.getItem("User-Data"));
var userId = user["_id"];
var useravatar = user["avatar"];
var username = user["username"];
var request = {
postedBy: userId,
posts_avatar: useravatar,
username: username,
content: $scope.postContent
};
//send to server
$http.post('api/social/newPost', request).success(function(response){
getPosts(true);
}).error(function(error){
console.log(error);
});
};
function getPosts(initial){
var data = {};
if ($scope.user){
data.ids = angular.copy($scope.user.friends);
data.ids.push($scope.user._id)
}
$http.post('api/social/getPost', data).success(function(response) {
if (initial) {
$scope.wallposts = response;
if (response.length == 0) {
getPosts(true);
} else {
$scope.wallposts = response;
}
} else {
if (response.length > $scope.wallposts.length) {
$scope.IncomingPosts = response;
}
}
});
};
$interval(function(){
getPosts(false);
if ($scope.IncomingPosts) {
$scope.difference = $scope.IncomingPosts.length - $scope.wallposts.length;
}
console.log("this is working");
}, 5000);
$scope.newP = function(){
console.log('getting new posts');
$scope.wallposts = angular.copy($scope.IncomingPosts);
$scope.IncomingPosts = undefined;
}
//Init
getPosts(true);
}]);
}());
Answers by Molda.
So maybe $scope.user.friends is undefined the first time so
angular.copy assigns undefined to data.ids, quick fix could be after
data.ids = angular.copy($scope.user.friends); do this if(!data.ids ||
!data.ids.length) data.ids = []
I'm having quite a hard time understanding how to chain promises. I'm writing login function for my app, leverating Loopback's Angular SDK. The objective, upon validating a user's credentials, is to confirm that the user's account is active, then fetch some additional properties including the user's role and set a flag to true if the user has admin privileges.
Here's my code...
$scope.login = function (user) {
User.login(user).$promise.then(
function (data) {
$rootScope.activeUser = data;
$rootScope.user_id = $rootScope.activeUser.user.username;
console.log('Active User: ', $rootScope.activeUser.user.email);
console.log('Status: ', $rootScope.activeUser.user.status);
if ($rootScope.activeUser.user.status === 'Y') {
$scope.loginError = false;
function checkAdmin(eid) {
Se_user.findById({
id: eid
}).$promise.then(
function (data1) {
var user_properties = data1;
if (user_properties.role === 'Admin') {
$rootScope.isAdmin = true;
console.log('isAdminInside: ', $rootScope.isAdmin);
return true;
} else {
//$rootScope.isAdmin = false;
return false;
}
});
};
var isAdmin = checkAdmin($rootScope.user_id);
console.log('isAdminOutside: ', $rootScope.isAdmin);
$state.go('home');
} else {
$scope.loginError = true;
$scope.loginErrorMessage = "Your account has been disabled. Please contact BMT Support for assistance";
}
},
function (err) {
console.log('Error: ', err)
$scope.loginError = true;
$scope.loginErrorMessage = "You've entered an invalid User ID or Password. Please try again.";
});
};
I've been troubleshooting by writing to the console, here's a sample of the output...
Active User: user#email.com
Status: Y
isAdminOutside: undefined
isAdminInside: true
How should I restructure so that the result of checkAdmin is properly returned after a successful login of an active user?
Try changing this part of code :
function checkAdmin(eid) {
return Se_user.findById({
id: eid
}).$promise.then(
function(data1) {
var user_properties = data1;
if (user_properties.role === 'Admin') {
$rootScope.isAdmin = true;
console.log('isAdminInside: ', $rootScope.isAdmin);
return true;
} else {
//$rootScope.isAdmin = false;
return false;
}
});
};
var isAdmin = checkAdmin($rootScope.user_id)
.then(function(val) {
console.log('isAdminOutside: ', val);
$state.go('home');
});
I have this code inside of a file called Auth.js .
hasRole: function(){
console.log(currentUser);
return currentUser.role; //role is an array of objects but gives undefined
}
I need to resolve the value of hasRole before redirecting anywhere just after login.
login looks like this:
var role=[];
login: function(user, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();
$http.post('/auth/local', {
email: user.email,
password: user.password
}).
success(function(data) {
$cookieStore.put('token', data.token);
currentUser = User.get();
console.log(currentUser);//gives an unresolved promise (output is given after this piece of code.
role = currentUser.role; //gives undefined
deferred.resolve(data);
return cb();
}).
error(function(err) {
this.logout();
deferred.reject(err);
return cb(err);
}.bind(this));
return deferred.promise;
}}
and is called as follows:
$scope.login = function(form) {
$scope.submitted = true;
if(form.$valid) {
Auth.login({
email: $scope.user.email,
password: $scope.user.password
})
.then( function() {
// Logged in, redirect to home
var role = Auth.hasRole();
console.log(role) //gives undefined.
//Need to redirect on basis of value of role
/*if(role.priority >= 1){
$location.path('/admincontrol');
}else{
$location.path('/');
}*/
})
.catch( function(err) {
$scope.errors.other = err.message;
});
}
};
How do I access currentUser.role here? I need to have its value in $scope.login just after login and just before redirecting so that I can redirect on basis of its value.
Edit: User service looks like this:
'use strict';
angular.module('createProjectApp')
.factory('User', function ($resource) {
// return $resource('/api/users/:id/:controller', {
return $resource('/api/customUsers/:id/:controller', {
id: '#_id'
},
{
changePassword: {
method: 'PUT',
params: {
controller:'password'
}
},
get: {
method: 'GET',
params: {
id:'me'
}
}
});
});
currentUser when consoled in login looked like this:
User.get() is itself a function that returns a promise. You are going to have to wait on the promise fullfillment before continuing, as in
currentUser.then(function() {
console.log(currentUser);
role = currentUser.role; //gives undefined
deferred.resolve(data);
return cb();
}
cb() itself is not needed since you are using promises - but you may have something special in mind.
I was wondering if anyone could point me in the right direction and help me fix this error I'm getting when I attempt to add a user with my Ember.js model after created a user with Firebases createUser method.
To be more specific here is the error I'm getting: Uncaught TypeError: Cannot read property 'createRecord' of undefined
App.SignUpController = Ember.Controller.extend({
needs: ['sign-in'],
needs: ['application'],
userSignedIn: false,
actions: {
signMeUp: function() {
var state = false;
var controllerContext = this;
// Create firebase user
ref.createUser({
email : this.get('email'),
password : this.get('password'),
}, function(error, user) {
if (error === null) {
console.log('User created with id', user.uid);
state = true;
controllerContext.set('userSignedIn', state);
console.log("State from sign-up page: "+ state);
console.log("Testing user.uid inside: "+user.uid);
var fbid = user.id;
controllerContext.set('user id', user.uid);
var newUser = this.store.createRecord('user', {
id: fbid,
email: this.get('email'),
password: this.get('password'),
});
newUser.save();
} else {
console.log("Error creating account:", error);
}
}); // End createUser
this.transitionToRoute('letters');
}
}
});
UPDATE: Here is a (very hacky) solution I came up with after a day of JS plumbing.
App.SignUpController = Ember.Controller.extend({
needs: ['sign-in'],
needs: ['application'],
userSignedIn: false,
thisUserID: '',
actions: {
signMeUp: function() {
var state = false;
var controllerContext = this;
// Create firebase user
function authWithPassCallback(userObj, user){
console.log("authWithPassCallback user.uid is: "+user.uid);
return user.uid
}
function createUserAndLogin(userObj, callback) {
ref.createUser(userObj, function(error, user) {
if (error === null) {
console.log("User created successfully");
controllerContext.set('thisUserID', user.uid);
return callback(userObj, user);
} else {
console.log("Error creating user:", error);
}
});
}
var userAndPass = {
email: this.get('email'),
password: this.get('password')}
var fbPayload = createUserAndLogin(userAndPass, authWithPassCallback);
setTimeout(function () {
console.log("FB load: "+ controllerContext.get('thisUserID'));
var newUser = controllerContext.store.createRecord('user', {
id: controllerContext.get('thisUserID'),
email: controllerContext.get("email"),
password: controllerContext.get("password"),
});
newUser.save();
controllerContext.transitionToRoute('letters');
}, 1000);
console.log(controllerContext.get('thisUserID'));
}
}
});
I'm assuming the error is occurring at newUser = this.store.createRecord - at this point in your code this is no longer referring to the controller. You will need to use controllerContext.store.createRecord.
you probably just lost the context here. this doesn't refer to the controller, you're in the error function.
There are two ways of fixing that. First is to bind the function to the controller's this:
ref.createUser({
// ...
}, function(error, user) {
var newUser = this.store.createRecord('user', {/*...*/});
// ...
}.bind(this));
or to reuse the controllerContext variable:
ref.createUser({
// ...
}, function(error, user) {
// ...
var newUser = controllerContext.store.createRecord('user', {/*...*/});
});