Last active
April 19, 2018 22:11
-
-
Save dig3/d39be98fdf52aeee0bfa to your computer and use it in GitHub Desktop.
Angular.js ES6 Login example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const TOKEN_KEY = 'auth.token'; | |
class AuthService { | |
constructor ($window) { | |
this.$window = $window; | |
} | |
isAuthenticated () { | |
var credentials; | |
credentials = this.getCredentials(); | |
return !!credentials.token; | |
} | |
setCredentials (token) { | |
this.$window.localStorage.setItem(TOKEN_KEY, token); | |
} | |
cleanCredentials () { | |
this.$window.localStorage.removeItem(TOKEN_KEY); | |
} | |
getCredentials () { | |
var token; | |
token = this.$window.localStorage.getItem(TOKEN_KEY); | |
return { | |
token: token | |
}; | |
} | |
} | |
AuthService.$inject = ['$window']; | |
export default AuthService; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// Workaround for not losing the this binding in methods | |
let self; | |
class AuthInterceptor { | |
constructor ($location, $q, ConfigService, AuthService) { | |
this.$location = $location; | |
this.$q = $q; | |
this.configService = ConfigService; | |
this.authService = AuthService; | |
this.API_LOGIN_URL = `${ConfigService.apiBase}/login/`; | |
self = this; | |
} | |
request (config) { | |
var canceller; | |
if (config.url.search(self.configService.apiBase) !== -1 && | |
self.authService.isAuthenticated()) { | |
config.headers.Authorization = `Token ${self.authService.getCredentials().token}`; | |
} else if (config.url.search(self.configService.apiBase) !== -1 && | |
config.url !== self.API_LOGIN_URL) { | |
canceller = self.$q.defer(); | |
config.timeout = canceller.promise; | |
canceller.resolve(`Cancelled request to ${config.url} because we do not have credentials`); | |
self.authService.cleanCredentials(); | |
self.$location.url('/login'); | |
} | |
return config; | |
} | |
responseError (rejection) { | |
if (rejection.config.url.search(self.configService.apiBase) !== -1 && | |
rejection.status === 401) { | |
// TODO: redirect parameter for login | |
self.authService.cleanCredentials(); | |
self.$location.url('/login'); | |
} | |
return self.$q.reject(rejection); | |
} | |
static factory ($location, $q, ConfigService, AuthService) { | |
return new AuthInterceptor($location, $q, ConfigService, AuthService); | |
} | |
} | |
AuthInterceptor.factory.$inject = ['$location', '$q','ConfigService', 'AuthService']; | |
export default AuthInterceptor.factory; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var ConfigService = { | |
apiBase: 'http://192.168.20.10/api' | |
}; | |
export default ConfigService; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
import { | |
AuthService, AuthInterceptorFactory, ConfigService, LoginService, NotifyService | |
} from './services'; | |
import LoginCtrl from './login.controller'; | |
var dependencies = [ | |
'ngAnimate', | |
'ngTouch', | |
'ngSanitize', | |
'ui.router', | |
'ui.bootstrap', | |
'cgNotify', | |
]; | |
angular.module('Webapp', dependencies) | |
.service('AuthService', AuthService) | |
.service('LoginService', LoginService) | |
.factory('AuthInterceptor', AuthInterceptorFactory) | |
.service('NotifyService', NotifyService) | |
.value('ConfigService', ConfigService) | |
.controller('LoginCtrl', LoginCtrl) | |
.config(($stateProvider, $urlRouterProvider) => { | |
$stateProvider | |
.state('login', { | |
url: '/login/', | |
templateUrl: 'login.html', | |
controller: 'LoginCtrl as vm' | |
}); | |
$urlRouterProvider.otherwise('/'); | |
}) | |
.config(($httpProvider) => | |
$httpProvider.interceptors.push('AuthInterceptor') | |
) | |
.config(($locationProvider) => | |
$locationProvider.html5Mode(true) | |
) | |
// Fix abstract states | |
.run(($rootScope, $state, $stateParams, notify) => { | |
$rootScope.$state = $state; | |
$rootScope.$stateParams = $stateParams; | |
notify.config({ | |
duration: 1000 * 5, // 5s | |
templateUrl: 'app/components/common/notify.html' | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
class LoginCtrl { | |
constructor ($state, NotifyService, LoginService) { | |
this.$state = $state; | |
this.notifyService = NotifyService; | |
this.loginService = LoginService; | |
this.loginInProgress = false; | |
} | |
login () { | |
this.notifyService.closeAll(); | |
this.loginInProgress = true; | |
this.loginService.login(this.email, this.password).then( | |
() => { | |
this.loginInProgress = false; | |
this.$state.go('dashboard'); | |
}, | |
(error) => { | |
this.loginInProgress = false; | |
this.showErrors(error); | |
} | |
); | |
} | |
showErrors (error) { | |
this.errors = error; | |
this.notifyService.error(error); | |
} | |
} | |
LoginCtrl.$inject = ['$state', 'NotifyService', 'LoginService']; | |
export default LoginCtrl; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="login"> | |
<div class="back-layer"></div> | |
<div class="container"> | |
<header class="row text-center"> | |
<h1>R</h1> | |
</header> | |
<form class="col-md-4 col-md-offset-4"> | |
<div class="form-group"> | |
<input type="email" class="form-control" id="email" placeholder="email" | |
ng-model="vm.email"> | |
</div> | |
<div class="form-group"> | |
<input type="password" class="form-control" id="password" placeholder="password" | |
ng-model="vm.password"> | |
</div> | |
<button type="submit" class="btn btn-default" ng-click="vm.login()">Login</button> | |
<span class="glyphicon glyphicon-refresh glyphicon-spin ng-hide" ng-show="vm.loginInProgress" aria-hidden="true"></span> | |
<a class="text-link" ui-sref="passwordReset">Forgot your password?</a> | |
</form> | |
</div> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
class LoginService { | |
constructor ($http, $q, $state, ConfigService, AuthService) { | |
this.$http = $http; | |
this.$q = $q; | |
this.$state = $state; | |
this.configService = ConfigService; | |
this.authService = AuthService; | |
if (AuthService.isAuthenticated() && | |
($state.current.name === 'home' || $state.current.name === 'login')) { | |
$state.go('dashboard'); | |
} | |
if (!AuthService.isAuthenticated() && $state.current.name !== 'home' && | |
$state.current.name !== 'login') { | |
$state.go('login'); | |
} | |
} | |
login (username, password) { | |
/*jshint camelcase: false */ | |
this.authService.cleanCredentials(); | |
return this.$http.post(`${this.configService.apiBase}/login/`, { | |
email: username, | |
password: password | |
}) | |
.success(data => { | |
this.authService.setCredentials(data.token); | |
this.signalsService.emit('renooit:login', username); | |
}) | |
.catch(error => this.$q.reject(error.data.non_field_errors[0])); | |
} | |
logout () { | |
return this.$http.get(`${this.configService.apiBase}/logout/`) | |
.success(() => { | |
this.authService.cleanCredentials(); | |
this.$state.go('login'); | |
}) | |
.catch(error => this.$q.reject(error.data)); | |
} | |
} | |
LoginService.$inject = [ | |
'$http', '$q', '$state', 'ConfigService', 'AuthService' | |
]; | |
export default LoginService; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
class NotifyService { | |
constructor (Notify) { | |
this.notifyService = Notify; | |
} | |
info (message, config) { | |
config = config || {}; | |
config.message = message; | |
config.classes = 'alert alert-info ' + (config.classes || ''); | |
return this.notifyService(config); | |
} | |
warn (message, config) { | |
config = config || {}; | |
config.message = message; | |
config.classes = 'alert alert-warning ' + (config.classes || ''); | |
return this.notifyService(config); | |
} | |
error (message, config) { | |
config = config || {}; | |
config.message = message; | |
config.classes = 'alert alert-danger ' + (config.classes || ''); | |
return this.notifyService(config); | |
} | |
success (message, config) { | |
config = config || {}; | |
config.message = message; | |
config.classes = 'alert alert-success ' + (config.classes || ''); | |
return this.notifyService(config); | |
} | |
notify (config) { | |
return this.notifyService(config); | |
} | |
closeAll () { | |
return this.notifyService.closeAll(); | |
} | |
} | |
NotifyService.$inject = ['notify']; | |
export default NotifyService; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
import AuthService from './auth'; | |
import ConfigService from './config'; | |
import LoginService from './login'; | |
import AuthInterceptorFactory from './authInterceptor'; | |
import NotifyService from './notify'; | |
export { | |
AuthService, | |
ConfigService, | |
LoginService, | |
AuthInterceptorFactory, | |
NotifyService | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment