I am building a small mobile app using ionic framework and angularJS. It will consume a Restful Web Service that requires authentication (User token). This means I need to keep my users token by myself. Could anyone tell me if there is room for improvement in my code. Specifically regarding to my "Session" service which I feel kind of useless. I based my development in this article.
.run(function ($rootScope, EVENTS, AuthService) {
$rootScope.$on('$stateChangeStart', function (event, next) {
if (next.requiresAuth === true && !AuthService.isAuthenticated()) {
event.preventDefault();
$rootScope.$broadcast(EVENTS.notAuthenticated);
console.log('You can not access here without login in.');
}
});
})
.constant('apiAddress', 'http://api.test.com')
.constant('EVENTS', {
loginSuccess: 'auth-login-success',
loginFailed: 'auth-login-failed',
logoutSuccess: 'auth-logout-success',
sessionTimeout: 'auth-session-timeout',
notAuthenticated: 'auth-not-authenticated',
signupSuccess: 'auth-signup-success'
})
.service('Session', function() {
this.create = function(user) {
this.user = user;
};
this.destroy = function() {
this.user = null;
}
return this;
})
.factory('AuthService', function($http, $rootScope, $localstorage, Session, apiAddress, EVENTS) {
var authService = {};
authService.login = function(credentials){
return $http.post(apiAddress + '/users/', credentials).then(function(res) {
Session.create(res.data);
$localstorage.setObject('user', res.data);
return res.data;
});
};
authService.signup = function(signForm){
return $http.post(apiAddress + '/users/', signForm).then(function(res) {
$rootScope.$broadcast(EVENTS.signupSuccess);
return res.data;
});
};
authService.logout = function(){
Session.destroy();
$localstorage.destroy('user');
$rootScope.$broadcast(EVENTS.logoutSuccess);
};
authService.isAuthenticated = function() {
return !!Session.user;
};
return authService;
})
controller('appCtrl', function($scope, $rootScope, $state, AuthService, EVENTS, $localstorage, Session) {
$scope.currentUser = null;
$scope.isAuthorized = AuthService.isAuthorized;
$scope.setCurrentUser = function (user) {
$scope.currentUser = user;
};
function logout() {
AuthService.logout();
}
function redirectToLogin() {
$state.go('login');
}
if ($localstorage.isSet('user') && Session.user == null) {
Session.create($localstorage.getObject('user'));
$scope.setCurrentUser($localstorage.getObject('user'))
$state.go('cobranzas.clientes.index');
}
// We listen to auth related broadcasts.
$scope.$on(EVENTS.notAuthenticated, logout);
$scope.$on(EVENTS.sessionTimeout, logout);
$scope.$on(EVENTS.signupSuccess, logout);
$scope.$on(EVENTS.logoutSuccess, redirectToLogin);
})
.controller('loginCtrl', function($scope, $rootScope, $state, EVENTS, AuthService) {
$scope.credentials = {
username: '',
password: ''
};
$scope.login = function (credentials) {
AuthService.login(credentials).then(function (user) {
$rootScope.$broadcast(EVENTS.loginSuccess);
$scope.setCurrentUser(user);
$state.go('index');
}, function () {
$rootScope.$broadcast(EVENTS.loginFailed);
});
};
})
.controller('signupCtrl', function($scope, $rootScope, $state, EVENTS, AuthService) {
$scope.signForm = {
FirstName: '',
LastName: '',
Password: '',
Country: '',
Phone: '',
Gender: '',
Position: ''
};
$scope.signup = function (signForm) {
AuthService.signup(signForm).then(function (data) {
$state.go('login');
}, function (data) {
console.log("Failed");
});
};
})
I dont feel right storing user in scope and in the service. Also I feel weird verifying localstorage in app controller. (App controller is a controller placed high at DOM so it's inherited by the others). Thanks you all very much!!!!
Not sure if you're still looking for answers, but I've been working on something really similar and noticed a couple of things:
You never define isAuthorized in AuthService, but you call it in AppCtrl in the line:
$scope.isAuthorized = AuthService.isAuthorized;
I would save currentUser in rootScope to ensure that it's available app-wide. Your use of localStorage seems pretty good to me.
Good luck! :)