<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS User Registration and Login Example</title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="jumbotron">
<div class="container">
<div class="col-sm-8 col-sm-offset-2">
<div ng-class="{ 'alert': flash, 'alert-success': flash.type === 'success', 'alert-danger': flash.type === 'error' }" ng-if="flash" ng-bind="flash.message"></div>
<div ui-view></div>
</div>
</div>
</div>
<div class="credits text-center">
<p>
<a href="http://www.coderr.net/index.php/2015/09/08/angularjs-user-registration-and-login-example/" target="_blank">AngularJS User Registration and Login Example</a>
</p>
<p>
<a href="http://www.coderr.net" target="_blank">Coderr.net</a><br>
<a href="http://www.coderr.net" target="_blank">
<img src="http://www.coderr.net/wp-content/uploads/2015/09/WB026JC1.png" alt="" width="299" height="150">
</a>
</p>
</div>
<script src="//code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="//code.angularjs.org/1.2.20/angular.js"></script>
<script data-require="ui-router@*" data-semver="0.2.15" src="//rawgit.com/angular-ui/ui-router/0.2.15/release/angular-ui-router.js"></script>
<script src="//code.angularjs.org/1.2.13/angular-cookies.js"></script>
<script src="main.js"></script>
<script src="authentication.service.js"></script>
<script src="flash.service.js"></script>
<!-- Real user service that uses an api -->
<!-- <script src="user.service.js"></script> -->
<!-- Fake user service for demo that uses local storage -->
<script src="user.service.local-storage.js"></script>
<script src="home.controller.js"></script>
<script src="login.controller.js"></script>
<script src="register.controller.js"></script>
</body>
</html>
/* Styles go here */
(function () {
'use strict';
angular
.module('app', ['ui.router', 'ngCookies'])
.config(config)
.run(run);
config.$inject = ['$stateProvider','$urlRouterProvider','$locationProvider'];
function config($stateProvider,$urlRouterProvider,$locationProvider) {
$stateProvider
.state('home', {
url: '/',
controller: 'HomeController',
templateUrl: 'home.html',
controllerAs: 'vm'
})
.state('login', {
url: '/login',
controller: 'LoginController',
templateUrl: 'login.html',
controllerAs: 'vm'
})
.state('register', {
url: '/register',
controller: 'RegisterController',
templateUrl: 'register.html',
controllerAs: 'vm'
})
$urlRouterProvider.otherwise('/login');
}
run.$inject = ['$rootScope', '$location', '$cookieStore', '$http'];
function run($rootScope, $location, $cookieStore, $http) {
// keep user logged in after page refresh
$rootScope.globals = $cookieStore.get('globals') || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.authdata; // jshint ignore:line
}
$rootScope.$on('$locationChangeStart', function (event, next, current) {
// redirect to login page if not logged in and trying to access a restricted page
var restrictedPage = $.inArray($location.path(), ['/login', '/register']) === -1;
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage && !loggedIn) {
$location.path('/login');
}
});
}
})();
<h1>Hi {{vm.user.firstName}}!</h1>
<p>You're logged in!!</p>
<h3>All registered users:</h3>
<ul>
<li ng-repeat="user in vm.allUsers">
{{user.username}} ({{user.firstName}} {{user.lastName}})
- <a href="" ng-click="vm.deleteUser(user.id)">Delete</a><br>
</li>
</ul>
<p> </p>
<p><a ui-sref="login" class="btn btn-primary">Logout</a></p>
<div class="col-md-6 col-md-offset-3">
<h2>Login</h2>
<div ng-show="vm.error" class="alert alert-danger">{{vm.error}}</div>
<form name="form" ng-submit="vm.login()" role="form">
<div class="form-group" ng-class="{ 'has-error': form.username.$dirty && form.username.$error.required }">
<label for="username">Username</label>
<input type="text" name="username" id="username" class="form-control" ng-model="vm.username" required />
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required }">
<label for="password">Password</label>
<input type="password" name="password" id="password" class="form-control" ng-model="vm.password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
</div>
<div class="form-actions">
<button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Login</button>
<img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
<a href="#/register" class="btn btn-link">Register</a>
</div>
</form>
</div>
<div class="col-md-6 col-md-offset-3">
<h2>Register</h2>
<div ng-show="vm.error" class="alert alert-danger">{{vm.error}}</div>
<form name="form" ng-submit="vm.register()" role="form">
<div class="form-group" ng-class="{ 'has-error': form.firstName.$dirty && form.firstName.$error.required }">
<label for="username">First name</label>
<input type="text" name="firstName" id="firstName" class="form-control" ng-model="vm.user.firstName" required />
<span ng-show="form.firstName.$dirty && form.firstName.$error.required" class="help-block">First name is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': form.lastName.$dirty && form.lastName.$error.required }">
<label for="username">Last name</label>
<input type="text" name="lastName" id="Text1" class="form-control" ng-model="vm.user.lastName" required />
<span ng-show="form.lastName.$dirty && form.lastName.$error.required" class="help-block">Last name is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': form.username.$dirty && form.username.$error.required }">
<label for="username">Username</label>
<input type="text" name="username" id="username" class="form-control" ng-model="vm.user.username" required />
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
</div>
<div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required }">
<label for="password">Password</label>
<input type="password" name="password" id="password" class="form-control" ng-model="vm.user.password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
</div>
<div class="form-actions">
<button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Register</button>
<img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
<a href="#/login" class="btn btn-link">Cancel</a>
</div>
</form>
</div>
(function () {
'use strict';
angular
.module('app')
.factory('AuthenticationService', AuthenticationService);
AuthenticationService.$inject = ['$http', '$cookieStore', '$rootScope', '$timeout', 'UserService'];
function AuthenticationService($http, $cookieStore, $rootScope, $timeout, UserService) {
var service = {};
service.Login = Login;
service.SetCredentials = SetCredentials;
service.ClearCredentials = ClearCredentials;
return service;
function Login(username, password, callback) {
/* Dummy authentication for testing, uses $timeout to simulate api call
----------------------------------------------*/
$timeout(function () {
var response;
UserService.GetByUsername(username)
.then(function (user) {
if (user !== null && user.password === password) {
response = { success: true };
} else {
response = { success: false, message: 'Username or password is incorrect' };
}
callback(response);
});
}, 1000);
/* Use this for real authentication
----------------------------------------------*/
//$http.post('/api/authenticate', { username: username, password: password })
// .success(function (response) {
// callback(response);
// });
}
function SetCredentials(username, password) {
var authdata = Base64.encode(username + ':' + password);
$rootScope.globals = {
currentUser: {
username: username,
authdata: authdata
}
};
$http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; // jshint ignore:line
$cookieStore.put('globals', $rootScope.globals);
}
function ClearCredentials() {
$rootScope.globals = {};
$cookieStore.remove('globals');
$http.defaults.headers.common.Authorization = 'Basic ';
}
}
// Base64 encoding service used by AuthenticationService
var Base64 = {
keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
encode: function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this.keyStr.charAt(enc1) +
this.keyStr.charAt(enc2) +
this.keyStr.charAt(enc3) +
this.keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
},
decode: function (input) {
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(input)) {
window.alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = this.keyStr.indexOf(input.charAt(i++));
enc2 = this.keyStr.indexOf(input.charAt(i++));
enc3 = this.keyStr.indexOf(input.charAt(i++));
enc4 = this.keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
}
};
})();
(function () {
'use strict';
angular
.module('app')
.factory('FlashService', FlashService);
FlashService.$inject = ['$rootScope'];
function FlashService($rootScope) {
var service = {};
service.Success = Success;
service.Error = Error;
initService();
return service;
function initService() {
$rootScope.$on('$locationChangeStart', function () {
clearFlashMessage();
});
function clearFlashMessage() {
var flash = $rootScope.flash;
if (flash) {
if (!flash.keepAfterLocationChange) {
delete $rootScope.flash;
} else {
// only keep for a single location change
flash.keepAfterLocationChange = false;
}
}
}
}
function Success(message, keepAfterLocationChange) {
$rootScope.flash = {
message: message,
type: 'success',
keepAfterLocationChange: keepAfterLocationChange
};
}
function Error(message, keepAfterLocationChange) {
$rootScope.flash = {
message: message,
type: 'error',
keepAfterLocationChange: keepAfterLocationChange
};
}
}
})();
(function () {
'use strict';
angular
.module('app')
.factory('UserService', UserService);
UserService.$inject = ['$timeout', '$filter', '$q'];
function UserService($timeout, $filter, $q) {
var service = {};
service.GetAll = GetAll;
service.GetById = GetById;
service.GetByUsername = GetByUsername;
service.Create = Create;
service.Update = Update;
service.Delete = Delete;
return service;
function GetAll() {
var deferred = $q.defer();
deferred.resolve(getUsers());
return deferred.promise;
}
function GetById(id) {
var deferred = $q.defer();
var filtered = $filter('filter')(getUsers(), { id: id });
var user = filtered.length ? filtered[0] : null;
deferred.resolve(user);
return deferred.promise;
}
function GetByUsername(username) {
var deferred = $q.defer();
var filtered = $filter('filter')(getUsers(), { username: username });
var user = filtered.length ? filtered[0] : null;
deferred.resolve(user);
return deferred.promise;
}
function Create(user) {
var deferred = $q.defer();
// simulate api call with $timeout
$timeout(function () {
GetByUsername(user.username)
.then(function (duplicateUser) {
if (duplicateUser !== null) {
deferred.resolve({ success: false, message: 'Username "' + user.username + '" is already taken' });
} else {
var users = getUsers();
// assign id
var lastUser = users[users.length - 1] || { id: 0 };
user.id = lastUser.id + 1;
// save to local storage
users.push(user);
setUsers(users);
deferred.resolve({ success: true });
}
});
}, 1000);
return deferred.promise;
}
function Update(user) {
var deferred = $q.defer();
var users = getUsers();
for (var i = 0; i < users.length; i++) {
if (users[i].id === user.id) {
users[i] = user;
break;
}
}
setUsers(users);
deferred.resolve();
return deferred.promise;
}
function Delete(id) {
var deferred = $q.defer();
var users = getUsers();
for (var i = 0; i < users.length; i++) {
var user = users[i];
if (user.id === id) {
users.splice(i, 1);
break;
}
}
setUsers(users);
deferred.resolve();
return deferred.promise;
}
// private functions
function getUsers() {
if(!localStorage.users){
localStorage.users = JSON.stringify([]);
}
return JSON.parse(localStorage.users);
}
function setUsers(users) {
localStorage.users = JSON.stringify(users);
}
}
})();
(function () {
'use strict';
angular
.module('app')
.controller('LoginController', LoginController);
LoginController.$inject = ['$location', 'AuthenticationService', 'FlashService'];
function LoginController($location, AuthenticationService, FlashService) {
var vm = this;
vm.login = login;
(function initController() {
// reset login status
AuthenticationService.ClearCredentials();
})();
function login() {
vm.dataLoading = true;
AuthenticationService.Login(vm.username, vm.password, function (response) {
if (response.success) {
AuthenticationService.SetCredentials(vm.username, vm.password);
$location.path('/');
} else {
FlashService.Error(response.message);
vm.dataLoading = false;
}
});
};
}
})();
(function () {
'use strict';
angular
.module('app')
.controller('RegisterController', RegisterController);
RegisterController.$inject = ['UserService', '$location', '$rootScope', 'FlashService'];
function RegisterController(UserService, $location, $rootScope, FlashService) {
var vm = this;
vm.register = register;
function register() {
vm.dataLoading = true;
UserService.Create(vm.user)
.then(function (response) {
if (response.success) {
FlashService.Success('Registration successful', true);
$location.path('/login');
} else {
FlashService.Error(response.message);
vm.dataLoading = false;
}
});
}
}
})();
(function () {
'use strict';
angular
.module('app')
.controller('HomeController', HomeController);
HomeController.$inject = ['UserService', '$rootScope'];
function HomeController(UserService, $rootScope) {
var vm = this;
vm.user = null;
vm.allUsers = [];
vm.deleteUser = deleteUser;
initController();
function initController() {
loadCurrentUser();
loadAllUsers();
}
function loadCurrentUser() {
UserService.GetByUsername($rootScope.globals.currentUser.username)
.then(function (user) {
vm.user = user;
});
}
function loadAllUsers() {
UserService.GetAll()
.then(function (users) {
vm.allUsers = users;
});
}
function deleteUser(id) {
UserService.Delete(id)
.then(function () {
loadAllUsers();
});
}
}
})();
(function () {
'use strict';
angular
.module('app')
.factory('UserService', UserService);
UserService.$inject = ['$http'];
function UserService($http) {
var service = {};
service.GetAll = GetAll;
service.GetById = GetById;
service.GetByUsername = GetByUsername;
service.Create = Create;
service.Update = Update;
service.Delete = Delete;
return service;
function GetAll() {
return $http.get('/api/users').then(handleSuccess, handleError('Error getting all users'));
}
function GetById(id) {
return $http.get('/api/users/' + id).then(handleSuccess, handleError('Error getting user by id'));
}
function GetByUsername(username) {
return $http.get('/api/users/' + username).then(handleSuccess, handleError('Error getting user by username'));
}
function Create(user) {
return $http.post('/api/users', user).then(handleSuccess, handleError('Error creating user'));
}
function Update(user) {
return $http.put('/api/users/' + user.id, user).then(handleSuccess, handleError('Error updating user'));
}
function Delete(id) {
return $http.delete('/api/users/' + id).then(handleSuccess, handleError('Error deleting user'));
}
// private functions
function handleSuccess(data) {
return data;
}
function handleError(error) {
return function () {
return { success: false, message: error };
};
}
}
})();