<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS User Registration and Login Example</title>
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
</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 ng-view></div>
</div>
</div>
</div>
<div class="credits text-center">
<p>
<a href="http://jasonwatmore.com/post/2015/03/10/AngularJS-User-Registration-and-Login-Example.aspx" target="_top">AngularJS User Registration and Login Example</a>
</p>
<p>
<a href="http://jasonwatmore.com" target="_top">JasonWatmore.com</a>
</p>
</div>
<script src="//code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="//code.angularjs.org/1.5.8/angular.js"></script>
<script src="//code.angularjs.org/1.5.8/angular-route.js"></script>
<script src="//code.angularjs.org/1.5.8/angular-cookies.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-messages/1.5.8/angular-messages.js"></script>
<script src="app.js"></script>
<script src="Authentication.Service.js"></script>
<script src="Flash.Service.js"></script>
<!-- Real user service that uses an api -->
<!-- <script src="//cdn.rawgit.com/cornflourblue/angular-registration-login-example/master/app-services/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>
(function () {
'use strict';
angular
.module('app', ['ngRoute', 'ngCookies', 'ngMessages'])
.config(config)
.run(run);
config.$inject = ['$routeProvider', '$locationProvider'];
function config($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
controller: 'HomeController',
templateUrl: 'home/home.view.html',
controllerAs: 'vm'
})
.when('/login', {
controller: 'LoginController',
templateUrl: 'login/login.view.html',
controllerAs: 'vm'
})
.when('/register', {
controller: 'RegisterController',
templateUrl: 'register/register.view.html',
controllerAs: 'vm'
})
.when('/coach', {
controller: 'HomeController',
templateUrl: 'coach/home.view.html',
controllerAs: 'vm'
})
.otherwise({ redirectTo: '/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');
}
});
}
})();
<div class="col-md-6 col-md-offset-3">
<h2>Login</h2>
<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 ripple">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>
<h1>Hi {{vm.user.firstName}}!</h1>
<p>You're logged in as a Parent!!</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>
</li>
</ul>
<p> </p>
<p><a href="#/login" class="btn btn-primary">Logout</a></p>
<div class="col-md-6 col-md-offset-3">
<h2>Register</h2>
<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="firstName">First name</label>
<input type="text" name="firstName" id="firstName" class="form-control" ng-model="vm.user.firstName" required minlength="3" maxlength="10" />
<div ng-messages="form.firstName.$dirty && form.firstName.$error" role="alert">
<div class="help-block" ng-message="minlength">This field must be over 3 characters long.</div>
<div class="help-block" ng-message="required">First name is required.</div>
<div class="help-block" ng-message="maxlength">This field can be at most 10 characters long.</div>
</div>
</div>
<div class="form-group" ng-class="{ 'has-error': form.lastName.$dirty && form.lastName.$error.required }">
<label for="lastName">Last name</label>
<input type="text" name="lastName" id="lastName" class="form-control ripple" 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-group" ng-class="{ 'has-error': form.userType.$dirty && form.userType.$error.required }">
<label for="userType">User Type</label>
<select name="userType" id="userType" class="form-control" ng-model="vm.user.userType" required>
<option value="Coach">Coach</option>
<option value="Parent">Parent</option>
</select>
<span ng-show="form.userType.$dirty && form.userType.$error.required" class="help-block">User Type 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>
<h1>Hi {{vm.user.firstName}}!</h1>
<p>You're logged in as a COUCH!!</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>
</li>
</ul>
<p> </p>
<p><a href="#/login" class="btn btn-primary">Logout</a></p>
(function () {
'use strict';
angular
.module('app')
.controller('LoginController', LoginController);
LoginController.$inject = ['$location', 'AuthenticationService', 'FlashService', '$rootScope'];
function LoginController($location, AuthenticationService, FlashService, $rootScope) {
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) {
alert("hi");
AuthenticationService.SetCredentials(vm.username, vm.password);
if(response.userType == "Coach"){
$location.path('/coach');
}
else{
$location.path('/');
}
} else {
FlashService.Error(response.message);
vm.dataLoading = false;
}
});
}
}
})();
(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) {
/* Use this for real authentication
----------------------------------------------*/
$http.post('http://localhost:39048/api/token', { Email: username, Password: password })
.then(function(response) {
callback(response);
}, function(response){
callback(response.data.Message);
});
/* 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, userType: user.userType };
// }
// else {
// response = { success: false, message: 'Username or password is incorrect' };
// }
// callback(response);
// });
// }, 1000);
}
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')
.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')
.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')
.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')
.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
};
}
}
})();
.ripple {
position: relative;
overflow: hidden
}
.ripple:after {
content: "";
background: black;
display: block;
position: absolute;
border-radius: 90%;
padding-top: 100%;
padding-left: 100%;
margin-top: -250%;
margin-left: -250%;
opacity: 0;
transition: all 2s
}
.ripple:active:after {
padding-top: 0;
padding-left: 0;
margin-top: 0;
margin-left: 0;
opacity: 1;
transition: 0s
}