Repository: stormpath/stormpath-sdk-angularjs
Branch: master
Commit: 8b2a1caf71ce
Files: 212
Total size: 563.4 KB
Directory structure:
gitextract_pr66l4um/
├── .gitignore
├── .gitmodules
├── .jshintrc
├── .npmignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gruntfile.js
├── LICENSE
├── OLD-README.md
├── README.md
├── TROUBLESHOOTING.md
├── bower.json
├── dist/
│ ├── stormpath-sdk-angularjs.js
│ └── stormpath-sdk-angularjs.tpls.js
├── docs/
│ ├── Makefile
│ ├── render
│ └── source/
│ ├── access_control.rst
│ ├── conf.py
│ ├── configure_angular.rst
│ ├── create_new_project.rst
│ ├── create_tenant.rst
│ ├── customize_menu.rst
│ ├── index.rst
│ ├── introduction.rst
│ ├── login.rst
│ ├── password_reset.rst
│ ├── protect_api.rst
│ ├── register.rst
│ ├── support.rst
│ ├── user_profile.rst
│ └── wait_for_user.rst
├── example/
│ ├── cors-app/
│ │ ├── .bowerrc
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── client/
│ │ │ ├── client.js
│ │ │ └── index.html
│ │ ├── package.json
│ │ └── server.js
│ ├── dashboard-app/
│ │ ├── .bowerrc
│ │ ├── .buildignore
│ │ ├── .editorconfig
│ │ ├── .gitattributes
│ │ ├── .gitignore
│ │ ├── .travis.yml
│ │ ├── .yo-rc.json
│ │ ├── Gruntfile.js
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── client/
│ │ │ ├── .htaccess
│ │ │ ├── .jshintrc
│ │ │ ├── app/
│ │ │ │ ├── app.css
│ │ │ │ ├── app.js
│ │ │ │ ├── forgot/
│ │ │ │ │ ├── forgot.controller.js
│ │ │ │ │ ├── forgot.controller.spec.js
│ │ │ │ │ ├── forgot.css
│ │ │ │ │ ├── forgot.html
│ │ │ │ │ └── forgot.js
│ │ │ │ ├── login/
│ │ │ │ │ ├── login.controller.js
│ │ │ │ │ ├── login.controller.spec.js
│ │ │ │ │ ├── login.css
│ │ │ │ │ ├── login.html
│ │ │ │ │ └── login.js
│ │ │ │ ├── main/
│ │ │ │ │ ├── main.controller.js
│ │ │ │ │ ├── main.controller.spec.js
│ │ │ │ │ ├── main.css
│ │ │ │ │ ├── main.html
│ │ │ │ │ └── main.js
│ │ │ │ ├── profile/
│ │ │ │ │ ├── profile.controller.js
│ │ │ │ │ ├── profile.controller.spec.js
│ │ │ │ │ ├── profile.css
│ │ │ │ │ ├── profile.html
│ │ │ │ │ └── profile.js
│ │ │ │ ├── register/
│ │ │ │ │ ├── register.controller.js
│ │ │ │ │ ├── register.controller.spec.js
│ │ │ │ │ ├── register.css
│ │ │ │ │ ├── register.html
│ │ │ │ │ └── register.js
│ │ │ │ ├── reset/
│ │ │ │ │ ├── reset.controller.js
│ │ │ │ │ ├── reset.controller.spec.js
│ │ │ │ │ ├── reset.css
│ │ │ │ │ ├── reset.html
│ │ │ │ │ └── reset.js
│ │ │ │ └── verify/
│ │ │ │ ├── verify.controller.js
│ │ │ │ ├── verify.controller.spec.js
│ │ │ │ ├── verify.css
│ │ │ │ ├── verify.html
│ │ │ │ └── verify.js
│ │ │ ├── components/
│ │ │ │ └── navbar/
│ │ │ │ ├── navbar.controller.js
│ │ │ │ └── navbar.html
│ │ │ ├── index.html
│ │ │ └── robots.txt
│ │ ├── e2e/
│ │ │ └── main/
│ │ │ ├── main.po.js
│ │ │ └── main.spec.js
│ │ ├── karma.conf.js
│ │ ├── package.json
│ │ ├── protractor.conf.js
│ │ └── server/
│ │ ├── .jshintrc
│ │ ├── .jshintrc-spec
│ │ ├── api/
│ │ │ └── thing/
│ │ │ ├── index.js
│ │ │ ├── thing.controller.js
│ │ │ └── thing.spec.js
│ │ ├── app.js
│ │ ├── components/
│ │ │ └── errors/
│ │ │ └── index.js
│ │ ├── config/
│ │ │ ├── environment/
│ │ │ │ ├── development.js
│ │ │ │ ├── index.js
│ │ │ │ ├── production.js
│ │ │ │ └── test.js
│ │ │ ├── express.js
│ │ │ └── local.env.sample.js
│ │ ├── routes.js
│ │ └── views/
│ │ └── 404.html
│ └── ng-route-app/
│ ├── .bowerrc
│ ├── .buildignore
│ ├── .editorconfig
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .travis.yml
│ ├── .yo-rc.json
│ ├── Gruntfile.js
│ ├── README.md
│ ├── bower.json
│ ├── client/
│ │ ├── .htaccess
│ │ ├── .jshintrc
│ │ ├── app/
│ │ │ ├── app.css
│ │ │ ├── app.js
│ │ │ ├── forgot/
│ │ │ │ ├── forgot.controller.js
│ │ │ │ ├── forgot.controller.spec.js
│ │ │ │ ├── forgot.css
│ │ │ │ ├── forgot.html
│ │ │ │ └── forgot.js
│ │ │ ├── login/
│ │ │ │ ├── login.controller.js
│ │ │ │ ├── login.controller.spec.js
│ │ │ │ ├── login.css
│ │ │ │ ├── login.html
│ │ │ │ └── login.js
│ │ │ ├── main/
│ │ │ │ ├── main.controller.js
│ │ │ │ ├── main.controller.spec.js
│ │ │ │ ├── main.css
│ │ │ │ ├── main.html
│ │ │ │ └── main.js
│ │ │ ├── profile/
│ │ │ │ ├── profile.controller.js
│ │ │ │ ├── profile.controller.spec.js
│ │ │ │ ├── profile.css
│ │ │ │ ├── profile.html
│ │ │ │ └── profile.js
│ │ │ ├── register/
│ │ │ │ ├── register.controller.js
│ │ │ │ ├── register.controller.spec.js
│ │ │ │ ├── register.css
│ │ │ │ ├── register.html
│ │ │ │ └── register.js
│ │ │ ├── reset/
│ │ │ │ ├── reset.controller.js
│ │ │ │ ├── reset.controller.spec.js
│ │ │ │ ├── reset.css
│ │ │ │ ├── reset.html
│ │ │ │ └── reset.js
│ │ │ └── verify/
│ │ │ ├── verify.controller.js
│ │ │ ├── verify.controller.spec.js
│ │ │ ├── verify.css
│ │ │ ├── verify.html
│ │ │ └── verify.js
│ │ ├── components/
│ │ │ └── navbar/
│ │ │ ├── navbar.controller.js
│ │ │ └── navbar.html
│ │ ├── index.html
│ │ └── robots.txt
│ ├── e2e/
│ │ └── main/
│ │ ├── main.po.js
│ │ └── main.spec.js
│ ├── karma.conf.js
│ ├── package.json
│ ├── protractor.conf.js
│ └── server/
│ ├── .jshintrc
│ ├── .jshintrc-spec
│ ├── api/
│ │ └── thing/
│ │ ├── index.js
│ │ ├── thing.controller.js
│ │ └── thing.spec.js
│ ├── app.js
│ ├── components/
│ │ └── errors/
│ │ └── index.js
│ ├── config/
│ │ ├── environment/
│ │ │ ├── development.js
│ │ │ ├── index.js
│ │ │ ├── production.js
│ │ │ └── test.js
│ │ ├── express.js
│ │ └── local.env.sample.js
│ ├── routes.js
│ └── views/
│ └── 404.html
├── index.js
├── ngdoc_assets/
│ ├── example/
│ │ └── index.ngdoc
│ ├── index.ngdoc
│ ├── nav.html
│ ├── server/
│ │ └── index.ngdoc
│ └── stormpath-angular.css
├── package.json
├── protractor.conf.js
├── src/
│ ├── module.js
│ ├── spEmailVerification.tpl.html
│ ├── spLoginForm.tpl.html
│ ├── spPasswordResetForm.tpl.html
│ ├── spPasswordResetRequestForm.tpl.html
│ ├── spRegistrationForm.tpl.html
│ ├── stormpath.auth.js
│ ├── stormpath.config.js
│ ├── stormpath.emailverification.js
│ ├── stormpath.login.js
│ ├── stormpath.oauth.js
│ ├── stormpath.passwordreset.js
│ ├── stormpath.registration.js
│ ├── stormpath.social-login.js
│ ├── stormpath.tokenStore.js
│ ├── stormpath.user.js
│ ├── stormpath.utils.js
│ └── stormpath.view-model.js
└── test/
├── .jshintrc
└── protractor/
└── login.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules
bower_components
build
.tmp
.idea
================================================
FILE: .gitmodules
================================================
[submodule "docs/source/_themes/stormpath"]
path = docs/source/_themes/stormpath
url = https://github.com/stormpath/stormpath-sphinx-theme.git
================================================
FILE: .jshintrc
================================================
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"globals": {
"angular": false
}
}
================================================
FILE: .npmignore
================================================
app
docs
example
ngdoc_assets
test
================================================
FILE: CHANGELOG.md
================================================
# 2.0.1
Fixed a bug in `$isCurrentDomain` that would incorrectly report a cross-domain situation in IE11.
# 2.0.0
This release adds support for the [Stormpath Client API][], which allows you to authenticate the user directly with Stormpath (authentication does not require special software in your server). The user receives an access token, which can be used to authorize requests on your server. If you need to authorize requests on your server, you will will want to use one of our SDKs to make that process simpler.
Please see the Readme for the new instructions for using the Client API.
## Breaking Changes
Social Login now requires the use of the Client API, you will need to enable the Client API for your Stormpath Application. This can be found under the Policies section of the application in our Admin Console.
# 1.1.1
Our UI Router integration will now look for `data.authorities` on UI state configuration, and apply the same behavior as `sp.authorize.group`. This is a convenience for [JHipster](https://jhipster.github.io/) users, as they
already use `data.authorities` to declare the roles that a user must have in order to access a view.
# 1.1.0
* The `$user.get()` method now takes a boolean `bypassCache` option, e.g. `$user.get(true)` will make a new request of the `/me` endpoint, instead of returning the user data that was already cached on login.
* Logout requests (which makes a POST to `/logout` on our framework integration) are now using `Content-Type: application/x-www-form-urlencoded`, in order to prevent an un-necessary OPTIONS request.
* Fixed #151, an un-intended catching of error responses on all HTTP responses. Now we only handle error responses that come from our known framework endpoints.
# 1.0.0
This version needs at least version `3.0.0` of [express-stormpath](https://github.com/stormpath/express-stormpath).
* Added support for the registration view model ([#119](https://github.com/stormpath/stormpath-sdk-angularjs/pull/119))
This allows you to customize the registration form using the Stormpath Express configuration:
*
* angular.module('myApp')
* .config(function ($stateProvider) {
*
* // Wait until we know if the user is logged in before showing the homepage
* $stateProvider
* .state('main', {
* url: '/',
* sp: {
* waitForUser: true
* }
* });
*
* // Require a user to be authenticated in order to see this state
* $stateProvider
* .state('secrets', {
* url: '/secrets',
* controller: 'SecretsCtrl',
* sp: {
* authenticate: true
* }
* });
*
* // Require a user to be in the admins group in order to see this state
* $stateProvider
* .state('secrets', {
* url: '/admin',
* controller: 'AdminCtrl',
* sp: {
* authorize: {
* group: 'admins'
* }
* }
* });
* });
*
*
* If using JHipster generated code:
*
*
* // Require a user to be in the admins group in order to see this state
* $stateProvider
* .state('secrets', {
* url: '/admin',
* controller: 'AdminCtrl',
* data: {
* authorities: ['admins']
* }
* });
*
*/
/**
* @ngdoc object
*
* @name stormpath.SpRouteConfig:SpRouteConfig
*
* @property {boolean} authenticate
*
* If `true`, the user must be authenticated in order to view this route.
* If the user is not authenticated, they will
* be redirected to the `login` route. After they login, they will be redirected to
* the route that was originally requested.
*
* @property {object} authorize
*
* An object that defines access control rules. Currently, it supports a group-based
* check. See the example below.
*
* @property {boolean} waitForUser
*
* If `true`, delay the route transition until we know
* if the user is authenticated or not. This is useful for situations where
* you want everyone to see this route, but the route may look different
* depending on the user's authentication route.
*
*
* @description
*
* The Stormpath Route Config is an object that you can define on a route.
* Use this configuration to define access control for your routes, as
* defined by the ngRoute module.
*
* You will need to be using the ngRoute module, and you need
* to enable the integration by calling
* {@link stormpath.$stormpath#methods_ngRouter $stormpath.ngRouter()} in your
* application's config block.
*
* If you're using UI Router instead of Angular's built-in `$routeProvider`, please
* use {@link stormpath.$stormpath#methods_uiRouter $stormpath.uiRouter()} instead.
*
* @example
*
*
*
* angular.module('myApp')
* .config(function ($routeProvider) {
* // Wait until we know if the user is logged in before showing the homepage
* $routeProvider
* .when('/main', {
* controller: 'MainCtrl',
* sp: {
* waitForUser: true
* }
* });
*
* // Require a user to be authenticated in order to see this route
* $routeProvider
* .when('/secrets', {
* controller: 'SecretsCtrl',
* sp: {
* authenticate: true
* }
* });
*
* // Require a user to be in the admins group in order to see this route
* $routeProvider
* .when('/secrets', {
* controller: 'AdminCtrl',
* sp: {
* authorize: {
* group: 'admins'
* }
* }
* });
* });
*
*/
angular.module('stormpath', [
'stormpath.CONFIG',
'stormpath.utils',
'stormpath.auth',
'stormpath.userService',
'stormpath.viewModelService',
'stormpath.socialLogin',
'stormpath.oauth'
])
.factory('StormpathAgentInterceptor',['$isCurrentDomain', '$spHeaders', function($isCurrentDomain, $spHeaders){
function StormpathAgentInterceptor(){
}
/**
* Adds the X-Stormpath-Agent header, if the requested URL is on the same
* domain as the current document.
*
* @param {Object} config $http config object.
* @return {Object} config $http config object.
*/
StormpathAgentInterceptor.prototype.request = function(config){
var uriExpressions = [
'/change$',
'/forgot$',
'/login$',
'/logout$',
'/me$',
'/oauth/token$',
'/oauth/token$',
'/register$',
'/revoke$',
'/verify$'
];
if (uriExpressions.some(function(expr){
return new RegExp(expr).test(config.url);
})) {
config.headers = angular.extend(config.headers, $spHeaders);
}
return config;
};
return new StormpathAgentInterceptor();
}])
.config(['$httpProvider',function($httpProvider){
$httpProvider.interceptors.push('StormpathAgentInterceptor');
}])
.provider('$stormpath', [function $stormpathProvider(){
/**
* @ngdoc object
*
* @name stormpath.$stormpath
*
* @description
*
* This service allows you to enable application-wide features of the library.
*
* At the moment the only feature is the UI Router integration, which is
* documented below.
*/
this.$get = [
'$user', '$injector', 'STORMPATH_CONFIG', '$rootScope', '$location',
function stormpathServiceFactory($user, $injector, STORMPATH_CONFIG, $rootScope, $location) {
var $state;
var $route;
function StormpathService(){
var encoder = new UrlEncodedFormParser();
this.encodeUrlForm = encoder.encode.bind(encoder);
if ($injector.has('$state')) {
$state = $injector.get('$state');
}
if ($injector.has('$route')) {
$route = $injector.get('$route');
}
return this;
}
function stateChangeUnauthenticatedEvent(toState, toParams){
/**
* @ngdoc event
*
* @name stormpath.$stormpath#$stateChangeUnauthenticated
*
* @eventOf stormpath.$stormpath
*
* @eventType broadcast on root scope
*
* @param {Object} event
*
* Angular event object.
*
* @param {Object} toState The state that the user attempted to access.
*
* @param {Object} toParams The state params of the state that the user
* attempted to access.
*
* @description
*
* This event is broadcast when a UI state change is prevented,
* because the user is not logged in.
*
* Use this event if you want to implement your own strategy for
* presenting the user with a login form.
*
* To receive this event, you must be using the UI Router integration.
*
* @example
*
*
* $rootScope.$on('$stateChangeUnauthenticated',function(e,toState,toParams){
* // Your custom logic for deciding how the user should login, and
* // if you want to redirect them to the desired state afterwards
* });
*
*/
$rootScope.$broadcast(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHENTICATED,toState,toParams);
}
function stateChangeUnauthorizedEvent(toState,toParams){
/**
* @ngdoc event
*
* @name stormpath.$stormpath#$stateChangeUnauthorized
*
* @eventOf stormpath.$stormpath
*
* @eventType broadcast on root scope
*
* @param {Object} event
*
* Angular event object.
*
* @param {Object} toState The state that the user attempted to access.
*
* @param {Object} toParams The state params of the state that the user
* attempted to access.
*
* @description
*
* This event is broadcast when a UI state change is prevented,
* because the user is not authorized by the rules defined in the
* {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configuration}
* for the requested state.
*
* Use this event if you want to implement your own strategy for telling
* the user that they are forbidden from viewing that state.
*
* To receive this event, you must be using the UI Router integration.
*
* @example
*
*
* $rootScope.$on('$stateChangeUnauthorized',function(e,toState,toParams){
* // Your custom logic for deciding how the user should be
* // notified that they are forbidden from this state
* });
*
*/
$rootScope.$broadcast(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHORIZED,toState,toParams);
}
StormpathService.prototype.stateChangeInterceptor = function stateChangeInterceptor(config) {
$rootScope.$on('$stateChangeStart', function(e,toState,toParams){
var sp = toState.sp || {}; // Grab the sp config for this state
var authorities = (toState.data && toState.data.authorities) ? toState.data.authorities : undefined;
if((sp.authenticate || sp.authorize || (authorities && authorities.length)) && (!$user.currentUser)){
e.preventDefault();
$user.get().then(function(){
// The user is authenticated, continue to the requested state
if(sp.authorize || (authorities && authorities.length)){
if(authorizeStateConfig(sp, authorities)){
$state.go(toState.name,toParams);
}else{
stateChangeUnauthorizedEvent(toState,toParams);
}
}else{
$state.go(toState.name,toParams);
}
},function(){
// The user is not authenticated, emit the necessary event
stateChangeUnauthenticatedEvent(toState,toParams);
});
}else if(sp.waitForUser && ($user.currentUser===null)){
e.preventDefault();
$user.get().finally(function(){
$state.go(toState.name,toParams);
});
}
else if($user.currentUser && (sp.authorize || (authorities && authorities.length))){
if(!authorizeStateConfig(sp, authorities)){
e.preventDefault();
stateChangeUnauthorizedEvent(toState,toParams);
}
}else if(toState.name===config.loginState){
/*
If the user is already logged in, we will redirect
away from the login page and send the user to the
post login state.
*/
if($user.currentUser!==false){
e.preventDefault();
$user.get().finally(function(){
if($user.currentUser && $user.currentUser.href){
$state.go(config.defaultPostLoginState);
} else {
$state.go(toState.name,toParams);
}
});
}
}
});
};
function authorizeStateConfig(spStateConfig, authorities){
var sp = spStateConfig;
if(sp && sp.authorize && sp.authorize.group) {
return $user.currentUser.inGroup(sp.authorize.group);
}else if(authorities){
// add support for reading from JHipster's data: { authorities: ['ROLE_ADMIN'] }
// https://github.com/stormpath/stormpath-sdk-angularjs/issues/190
var roles = authorities.filter(function(authority){
return $user.currentUser.inGroup(authority);
});
return roles.length > 0;
}else{
console.error('Unknown authorize configuration for spStateConfig',spStateConfig);
return false;
}
}
function routeChangeUnauthenticatedEvent(toRoute) {
/**
* @ngdoc event
*
* @name stormpath.$stormpath#$routeChangeUnauthenticated
*
* @eventOf stormpath.$stormpath
*
* @eventType broadcast on root scope
*
* @param {Object} event
*
* Angular event object.
*
* @param {Object} toRoute The route that the user attempted to access.
*
* @description
*
* This event is broadcast when a route change is prevented,
* because the user is not logged in.
*
* Use this event if you want to implement your own strategy for
* presenting the user with a login form.
*
* To receive this event, you must be using the ngRoute module.
*
* @example
*
*
* $rootScope.$on('$routeChangeUnauthenticated', function(event, toRoute) {
* // Your custom logic for deciding how the user should login, and
* // if you want to redirect them to the desired route afterwards
* });
*
*/
$rootScope.$broadcast(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHENTICATED, toRoute);
}
function routeChangeUnauthorizedEvent(toRoute) {
/**
* @ngdoc event
*
* @name stormpath.$stormpath#$routeChangeUnauthorized
*
* @eventOf stormpath.$stormpath
*
* @eventType broadcast on root scope
*
* @param {Object} event
*
* Angular event object.
*
* @param {Object} toRoute The route that the user attempted to access.
*
* @description
*
* This event is broadcast when a route change is prevented,
* because the user is not authorized by the rules defined in the
* {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configuration}
* for the requested route.
*
* Use this event if you want to implement your own strategy for telling
* the user that they are forbidden from viewing that route.
*
* To receive this event, you must be using the ngRoute module.
*
* @example
*
*
* $rootScope.$on('$routeChangeUnauthorized', function(event, toRoute) {
* // Your custom logic for deciding how the user should be
* // notified that they are forbidden from this route
* });
*
*/
$rootScope.$broadcast(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHORIZED, toRoute);
}
StormpathService.prototype.routeChangeInterceptor = function routeChangeInterceptor(config) {
function goToRoute(route) {
setTimeout(function() {
if (route.$$route.originalPath === $location.path()) {
$route.reload();
} else {
$location.path(route);
}
});
}
$rootScope.$on('$routeChangeStart', function(event, toRoute) {
if (!toRoute.$$route) {
return;
}
var sp = toRoute.$$route.sp || {}; // Grab the sp config for this route
if ((sp.authenticate || sp.authorize) && !$user.currentUser) {
event.preventDefault();
$user.get().then(function() {
// The user is authenticated, continue to the requested route
if (sp.authorize) {
if (authorizeStateConfig(sp)) {
goToRoute(toRoute);
} else {
stateChangeUnauthorizedEvent(toRoute);
}
} else {
goToRoute(toRoute);
}
}, function() {
// The user is not authenticated, emit the necessary event
routeChangeUnauthenticatedEvent(toRoute);
});
} else if (sp.waitForUser && $user.currentUser === null) {
event.preventDefault();
$user.get().finally(function() {
goToRoute(toRoute);
});
} else if ($user.currentUser && sp.authorize) {
if (!authorizeStateConfig(sp)) {
event.preventDefault();
routeChangeUnauthorizedEvent(toRoute);
}
} else if (toRoute.$$route.originalPath === config.loginRoute) {
/*
If the user is already logged in, we will redirect
away from the login page and send the user to the
post login route.
*/
if ($user.currentUser && $user.currentUser.href) {
event.preventDefault();
goToRoute(config.defaultPostLoginRoute);
}
}
});
};
function authorizeRouteConfig(spRouteConfig) {
var sp = spRouteConfig;
if (sp && sp.authorize && sp.authorize.group) {
return $user.currentUser.inGroup(sp.authorize.group);
}
console.error('Unknown authorize configuration for spRouteConfig', sp);
return false;
}
/**
* @ngdoc function
*
* @name stormpath#uiRouter
*
* @methodOf stormpath.$stormpath
*
* @param {object} config
*
* * **`autoRedirect`** - Defaults to true. After the user logs in at
* the state defined by `loginState`, they will be redirected back to the
* state that was originally requested.
*
* * **`defaultPostLoginState`** - Where the user should be sent, after login,
* if they have visited the login page directly. If you do not define a value,
* nothing will happen at the login state. You can alternatively use the
* {@link stormpath.authService.$auth#events_$authenticated $authenticated} event to know
* that login is successful.
*
* * **`forbiddenState`** - The UI state name that we should send the user
* to if they try to an access a view that they are not authorized to view.
* This happens in response to an `authorize` rule in one of your
* {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configurations}
*
* * **`loginState`** - The UI state name that we should send the user
* to if they need to login. You'll probably use `login` for this value.
*
* @description
*
* Call this method to enable the integration with the UI Router module.
*
* When enabled, you can define {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configurations} on your UI states.
* This object allows you to define access control for the state.
*
* You can pass config options to this integration, the options control the
* default behavior around "need to login" and "forbidden" situations.
* If you wish to implement your own logic for these situations, simply
* omit the options and use the events (documented below) to know
* what is happening in the application.
*
* @example
*
*
* angular.module('myApp')
* .run(function($stormpath){
* $stormpath.uiRouter({
* forbiddenState: 'forbidden',
* defaultPostLoginState: 'main',
* loginState: 'login'
* });
* });
*
*/
StormpathService.prototype.uiRouter = function uiRouter(config){
var self = this;
config = typeof config === 'object' ? config : {};
this.stateChangeInterceptor(config);
if(config.loginState){
self.unauthenticatedWather = $rootScope.$on(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHENTICATED,function(e,toState,toParams){
self.postLogin = {
toState: toState,
toParams: toParams
};
$state.go(config.loginState);
});
}
$rootScope.$on(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME,function(){
if(self.postLogin && (config.autoRedirect !== false)){
$state.go(self.postLogin.toState,self.postLogin.toParams).then(function(){
self.postLogin = null;
});
}else if(config.defaultPostLoginState){
$state.go(config.defaultPostLoginState);
}
});
if(config.forbiddenState){
self.forbiddenWatcher = $rootScope.$on(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHORIZED,function(){
$state.go(config.forbiddenState);
});
}
};
/**
* @ngdoc function
*
* @name stormpath#ngRouter
*
* @methodOf stormpath.$stormpath
*
* @param {object} config
*
* * **`autoRedirect`** - Defaults to true. After the user logs in at
* the route defined by `loginRoute`, they will be redirected back to the
* route that was originally requested.
*
* * **`defaultPostLoginRoute`** - Where the user should be sent, after login,
* if they have visited the login page directly. If you do not define a value,
* nothing will happen at the login route. You can alternatively use the
* {@link stormpath.authService.$auth#events_$authenticated $authenticated} event to know
* that login is successful.
*
* * **`forbiddenRoute`** - The route that we should send the user
* to if they try to an access a view that they are not authorized to view.
* This happens in response to an `authorize` rule in one of your
* {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configurations}
*
* * **`loginRoute`** - The route name that we should send the user
* to if they need to login. You'll probably use `login` for this value.
*
* @description
*
* Call this method to enable the integration with the ngRoute module.
*
* When enabled, you can define {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configurations} on your routes.
* This object allows you to define access control for the route.
*
* You can pass config options to this integration, the options control the
* default behavior around "need to login" and "forbidden" situations.
* If you wish to implement your own logic for these situations, simply
* omit the options and use the events (documented below) to know
* what is happening in the application.
*
* @example
*
*
* angular.module('myApp')
* .run(function($stormpath){
* $stormpath.ngRouter({
* forbiddenRoute: '/forbidden',
* defaultPostLoginRoute: '/home',
* loginRoute: '/login'
* });
* });
*
*/
StormpathService.prototype.ngRouter = function ngRouter(config) {
var self = this;
config = typeof config === 'object' ? config : {};
this.routeChangeInterceptor(config);
if (config.loginRoute) {
this.unauthenticatedWather = $rootScope.$on(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHENTICATED, function(event, toRoute) {
self.postLogin = {
toRoute: toRoute
};
$location.path(config.loginRoute);
});
}
$rootScope.$on(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME, function() {
if (self.postLogin && config.autoRedirect !== false) {
$location.path(self.postLogin.toRoute);
self.postLogin = null;
} else if (config.defaultPostLoginRoute) {
$location.path(config.defaultPostLoginRoute);
}
});
if (config.forbiddenRoute) {
this.forbiddenWatcher = $rootScope.$on(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHORIZED, function() {
$location.path(config.forbiddenRoute);
});
}
};
StormpathService.prototype.regexAttrParser = function regexAttrParser(value){
var expr;
if(value instanceof RegExp){
expr = value;
}else if(value && /^\/.+\/[gim]?$/.test(value)){
expr = new RegExp(value.split('/')[1],value.split('/')[2]);
}else{
expr = value;
}
return expr;
};
function UrlEncodedFormParser(){
// Copy & modify from https://github.com/hapijs/qs/blob/master/lib/stringify.js
this.delimiter = '&';
this.arrayPrefixGenerators = {
brackets: function (prefix) {
return prefix + '[]';
},
indices: function (prefix, key) {
return prefix + '[' + key + ']';
},
repeat: function (prefix) {
return prefix;
}
};
return this;
}
UrlEncodedFormParser.prototype.stringify = function stringify(obj, prefix, generateArrayPrefix) {
if (obj instanceof Date) {
obj = obj.toISOString();
}
else if (obj === null) {
obj = '';
}
if (typeof obj === 'string' ||
typeof obj === 'number' ||
typeof obj === 'boolean') {
return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];
}
var values = [];
if (typeof obj === 'undefined') {
return values;
}
var objKeys = Object.keys(obj);
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];
if (Array.isArray(obj)) {
values = values.concat(this.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));
}
else {
values = values.concat(this.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));
}
}
return values;
};
UrlEncodedFormParser.prototype.encode = function encode(obj, options) {
options = options || {};
var delimiter = typeof options.delimiter === 'undefined' ? this.delimiter : options.delimiter;
var keys = [];
if (typeof obj !== 'object' ||
obj === null) {
return '';
}
var arrayFormat;
if (options.arrayFormat in this.arrayPrefixGenerators) {
arrayFormat = options.arrayFormat;
}
else if ('indices' in options) {
arrayFormat = options.indices ? 'indices' : 'repeat';
}
else {
arrayFormat = 'indices';
}
var generateArrayPrefix = this.arrayPrefixGenerators[arrayFormat];
var objKeys = Object.keys(obj);
for (var i = 0, il = objKeys.length; i < il; ++i) {
var key = objKeys[i];
keys = keys.concat(this.stringify(obj[key], key, generateArrayPrefix));
}
return keys.join(delimiter);
};
return new StormpathService();
}
];
}])
.run(['$rootScope','$user','STORMPATH_CONFIG',function($rootScope,$user,STORMPATH_CONFIG){
$rootScope.user = $user.currentUser || null;
$user.get().finally(function(){
$rootScope.user = $user.currentUser;
});
$rootScope.$on(STORMPATH_CONFIG.GET_USER_EVENT,function(){
$rootScope.user = $user.currentUser;
});
$rootScope.$on(STORMPATH_CONFIG.SESSION_END_EVENT,function(){
$rootScope.user = $user.currentUser;
});
$rootScope.$on(STORMPATH_CONFIG.SESSION_END_ERROR_EVENT,function(event, error){
console.error('Logout error', error);
});
$rootScope.$on(STORMPATH_CONFIG.UNAUTHENTICATED_EVENT,function(event, error){
console.error('UNAUTHENTICATED_EVENT');
});
}])
/**
* @ngdoc directive
*
* @name stormpath.ifUser:ifUser
*
* @description
*
* Use this directive to conditionally show an element if the user is logged in.
*
* @example
*
* **/ .directive('ifUser',['$user','$rootScope',function($user,$rootScope){ return { link: function(scope,element){ $rootScope.$watch('user',function(user){ if(user && user.href){ element.removeClass('ng-hide'); }else{ element.addClass('ng-hide'); } }); } }; }]) /** * @ngdoc directive * * @name stormpath.ifNotUser:ifNotUser * * @description * * Use this directive to conditionally show an element if the user is NOT logged in. * * @example * ***Hello, {{user.fullName}}
*
**/ .directive('ifNotUser',['$user','$rootScope',function($user,$rootScope){ return { link: function(scope,element){ $rootScope.$watch('user',function(user){ if(user && user.href){ element.addClass('ng-hide'); }else{ element.removeClass('ng-hide'); } }); } }; }]) /** * @ngdoc directive * * @name stormpath.ifUserInGroup:ifUserInGroup * * @description * * Use this directive to conditionally show an element if the user is logged in * and is a member of the group that is specified by the expression. * * The attribute value MUST be one of: * * * A string expression, surrounded by quotes * * A reference to a property on the $scope. That property can be a string or * regular expression. * * **Note**: This feature depends on the data that is returned by the * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_CURRENT_USER_URI CURRENT_USER_URI}. * Your server should expand the account's groups before returning the user. * If you are using [express-stormpath](https://github.com/stormpath/express-stormpath), simply use * [Automatic Expansion](http://docs.stormpath.com/nodejs/express/latest/user_data.html#automatic-expansion) * * # Using Regular Expressions * * If using a string expression as the attribute value, you can pass a regular * expression by wrapping it in the literal * syntax, e.g. * * `'/admins/'` would match any group which has *admins* in the name * * `'/admin$/'` would match any group were the name **ends with** *admin* * * If referencing a scope property, you should create the value as a RegExp type, * e.g.: * ***Hello, you need to login
*
* $scope.matchGroup = new RegExp(/admins/); ** * All regular expressions are evaluated via * [RegExp.prototype.test](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test) * * @example * *
*