module Happstack.Authenticate.Controller where
import Data.Text (Text)
import qualified Data.Text as T
import Happstack.Authenticate.Core (AuthenticateURL)
import Language.Javascript.JMacro
import Web.Routes (RouteT, askRouteFn)
authenticateCtrl :: (Monad m) => RouteT AuthenticateURL m JStat
authenticateCtrl =
do fn <- askRouteFn
return $ authenticateCtrlJs fn
authenticateCtrlJs :: (AuthenticateURL -> [(Text, Maybe Text)] -> Text) -> JStat
authenticateCtrlJs showURL = [jmacro|
{
//this is used to parse the profile
function url_base64_decode(str) {
var output = str.replace('-', '+').replace('_', '/');
switch (output.length % 4) {
case 0:
break;
case 2:
output += '==';
break;
case 3:
output += '=';
break;
default:
throw 'Illegal base64url string!';
}
return window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
}
// declare happstackAuthentication module
var happstackAuthentication = angular.module('happstackAuthentication', []);
// add controller
happstackAuthentication.controller('AuthenticationCtrl', ['$scope', 'userService', function ($scope, userService) {
$scope.isAuthenticated = userService.getUser().isAuthenticated;
$scope.$watch(function () { return userService.getUser().isAuthenticated; }, function(newVal, oldVal) { $scope.isAuthenticated = newVal; });
$scope.claims = userService.getUser().claims;
$scope.$watch(function () { return userService.getUser().claims; },
function(newVal, oldVal) { $scope.claims = newVal; }
);
$scope.logout = function () {
userService.clearUser();
document.cookie = 'atc=; path=/; expires=Thu, 01Jan70 00:00:01 GMT;';
};
}]);
happstackAuthentication.factory('authInterceptor', ['$rootScope', '$q', '$window', 'userService', function ($rootScope, $q, $window, userService) {
return {
'request': function (config) {
config.headers = config.headers || {};
u = userService.getUser();
if (u && u.token) {
config.headers.Authorization = 'Bearer ' + u.token;
}
return config;
},
'responseError': function (rejection) {
if (rejection.status === 401) {
// handle the case where the user is not authenticated
userService.clearUser();
document.cookie = 'atc=; path=/; expires=Thu, 01Jan70 00:00:01 GMT;';
}
return $q.reject(rejection);
}
};
}]);
happstackAuthentication.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
}]);
// add userService
happstackAuthentication.factory('userService', ['$rootScope', function ($rootScope) {
var service = {
userCache: null,
userCacheInit: function () {
var item = localStorage.getItem('user');
if (item) {
// alert('getUser: ' + item);
this.setUser(JSON.parse(item));
} else {
// alert('no user saved.');
service.clearUser();
}
},
updateFromToken: function (token) {
var encodedClaims = token.split('.')[1];
var claims = JSON.parse(url_base64_decode(encodedClaims));
u = this.getUser();
u.isAuthenticated = true;
u.token = token;
u.claims = claims;
// alert(JSON.stringify(u));
this.setUser(u);
return(u);
},
setUser: function(u) {
// alert('setUser:' + JSON.stringify(u));
this.userCache = u;
localStorage.setItem('user', JSON.stringify(u));
},
getUser: function() {
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
}
return "";
};
if (getCookie('atc').length == 0 && this.userCache.isAuthenticated == true)
this.clearUser();
return(this.userCache);
},
clearUser: function () {
// alert('clearUser');
this.setUser({ isAuthenticated: false,
claims: {},
token: null
});
}
};
service.userCacheInit();
return service;
}]);
}
|]