Having a little trouble with my authentication service. I basically have this on my service:
angular.factory('authentication', [..., function() {
var currentUser = {};
return {
login: function() {
currentUser = { username: 'Foo' };
},
logout: function() {
currentUser = {};
}
user: currentUser;
}
})]
And in my AppCtrl, I have this:
angular.module('App').controller('AppCtrl', [..., function() {
$rootScope.$on('$stateChangeSuccess', function() {
console.log(authentication.user);
});
}]);
In my LogoutCtrl, I have this:
angular.controller('LogoutCtrl', [..., function() {
authentication.logout();
$state.go('login');
}]);
Once the state changes to login, the console still prints username: 'Foo'.
Any ideas?
When you make the first assignment in the object you are referring to the reference of the user. You then replace that reference when you call logout() so your old user, bound earlier, is unchanged. Change it to a getter function instead:
...
getUser: function() {
return user; // always the correct reference
}
Now call that in the console.log and it will work
angular.factory('authentication', [..., function() {
var currentUser = {};
return {
login: function() {
currentUser = { username: 'Foo' };
},
logout: function() {
currentUser = {};
}
user: currentUser;
}
})]
Your login/logout methods change the value of the variable currentUser. These changes are not propagated to the authentication.property.
Two possible fixes:
1) Use this.user instead of var currentUser:
angular.factory('authentication', [..., function() {
return {
login: function() {
this.user = { username: 'Foo' };
},
logout: function() {
this.user = {};
}
user: {};
}
})]
2) Implement user as a getter-based property:
angular.factory('authentication', [..., function() {
var currentUser = {};
var auth = {
login: function() {
currentUser = { username: 'Foo' };
},
logout: function() {
currentUser = {};
}
};
Object.defineProperty(auth, 'user', {
get: function() { return currentUser; }
});
return svc;
})]
Related
I'm using ng-file-upload for uploading image in my project but
whenever I implement localStorage using AuthFactory.setToken({token: "secret_token", expires: 'time'}); ng-file-upload fails to send image to server. It does not conflict with AuthFactory.setUser(user_obj)
.factory('AuthFactory', ['LSFactory', function(LSFactory) {
var userKey = 'user';
var tokenKey = 'token';
var AuthAPI = {
isLoggedIn: function() {
return this.getUser() === null ? false : true;
},
getUser: function() {
return LSFactory.get(userKey);
},
setUser: function(user) {
return LSFactory.set(userKey, user);
},
getToken: function() {
return LSFactory.get(tokenKey);
},
setToken: function(token) {
return LSFactory.set(tokenKey, token);
},
deleteAuth: function() {
LSFactory.delete(userKey);
LSFactory.delete(tokenKey);
}
};
return AuthAPI;
}])
.factory('LSFactory', [function() {
var LSAPI = {
clear: function() {
return localStorage.clear();
},
get: function(key) {
return JSON.parse(localStorage.getItem(key));
},
set: function(key, data) {
return localStorage.setItem(key, JSON.stringify(data));
},
delete: function(key) {
return localStorage.removeItem(key);
},
getAll: function() {
var books = [];
var items = Object.keys(localStorage);
for (var i = 0; i < items.length; i++) {
if (items[i] !== 'user' || items[i] != 'token') {
books.push(JSON.parse(localStorage[items[i]]));
}
}
return books;
}
};
return LSAPI;
}])
I've a Vue component as follows:
import '../forms/form.js'
import '../forms/errors.js'
export default{
data(){
return{
form: new NewForm({
email: '',
password: '',
intendedUrl: '',
message: ''
})
}
},
methods: {
/**
* Login the user
*/
login(e) {
e.preventDefault();
this.form.startProcessing();
this.$http.post('/login/authenticate', this.form)
.then(function(response) {
this.form.finishProcessing();
},
function(response) {
this.form.setErrors(response.data);
});
}
}
}
The form.js file is
window.NewForm = function (data) {
var form = this;
$.extend(this, data);
this.errors = new NewFormErrors();
this.busy = false;
this.successful = false;
this.startProcessing = function () {
form.errors.forget();
form.busy = true;
form.successful = false;
};
this.setErrors = function (errors) {
console.log('okkk');
form.busy = false;
form.errors.set(errors);
}
};
and error.js
window.NewFormErrors = function () {
this.errors = {};
this.set = function (errors) {
console.log(errors);
this.errors= errors;
};
};
Here, the this.form.startProcessing(); seems working. But I'm not able to get the data passed to the this.setErrors. console.log(errors) returns nothing. Or it's not getting executed.
I have not recreated all of your solution but I will suspect the meaning of the value of this in the deferred execution so I will try to modify the code to:
login(e) {
e.preventDefault();
var that = this ;
this.form.startProcessing();
this.$http.post('/login/authenticate', this.form)
.then(function(response) {
that.form.finishProcessing();},
function(response) {
that.form.setErrors(response.data); });
}
I hope it will help.
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.
i try to make a getter and setter for the Supercontainer object, but it dose not seems to work.
PrometeiaECAProModuleMain.factory('ParameterFactory', [function () {
var Supercontainer = function (userId, supercontainerId, bankId) {
this.userId = userId;
this.supercontainerId = supercontainerid;
this.bankId = bankId;
};
return {
setSupercontainerParam: function (userId, supercontainerid, bank) {
supercontainer = new Supercontainer(userId, supercontainerid, bank);
},
getSupercontainerParam: function () {
return supercontainer;
}
};
}]);
I use it like this in my service.js
.factory('CommonService', function ($http, $state, Ls, md5, $filter) {
var headInfo = [];
return {
setData: function (key, data) {
headInfo[key] = data;
},
getData: function (key) {
return headInfo[key];
}
});
In the Controller you would set ur data like this
CommonService.setData('Dataname',{name:bla, price:25});
CommonService.getData('Dataname');
So I can pass all my data from one Controller to another and have it available everywhere
Service example. Can access the functions with ParameterFactory.getSupercontainer();
PrometeiaECAProModuleMain.service('ParameterFactory', function () {
var data = {};
this.setSupercontainer = function (userId, supercontainerId, bankId) {
data = {
'userId': userId,
'supercontainerId': supercontainerId,
'bankId': bankId
};
}
this.getSupercontainer = function () {
return data;
}
});
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', {/*...*/});
});