[
  {
    "path": ".gitignore",
    "content": "node_modules\nbower_components\nbuild\n.tmp\n.idea\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"docs/source/_themes/stormpath\"]\n\tpath = docs/source/_themes/stormpath\n\turl = https://github.com/stormpath/stormpath-sphinx-theme.git\n"
  },
  {
    "path": ".jshintrc",
    "content": "{\n  \"node\": true,\n  \"browser\": true,\n  \"esnext\": true,\n  \"bitwise\": true,\n  \"camelcase\": true,\n  \"curly\": true,\n  \"eqeqeq\": true,\n  \"immed\": true,\n  \"indent\": 2,\n  \"latedef\": true,\n  \"newcap\": true,\n  \"noarg\": true,\n  \"quotmark\": \"single\",\n  \"regexp\": true,\n  \"undef\": true,\n  \"unused\": true,\n  \"strict\": true,\n  \"trailing\": true,\n  \"smarttabs\": true,\n  \"globals\": {\n    \"angular\": false\n  }\n}\n"
  },
  {
    "path": ".npmignore",
    "content": "app\ndocs\nexample\nngdoc_assets\ntest\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# 2.0.1\n\nFixed a bug in `$isCurrentDomain` that would incorrectly report a cross-domain situation in IE11.\n\n# 2.0.0\n\nThis 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.\n\nPlease see the Readme for the new instructions for using the Client API.\n\n## Breaking Changes\n\nSocial 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.\n\n# 1.1.1\n\nOur 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\nalready use `data.authorities` to declare the roles that a user must have in order to access a view.\n\n# 1.1.0\n\n* 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.\n\n* 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.\n\n* 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.\n\n# 1.0.0\n\nThis version needs at least version `3.0.0` of [express-stormpath](https://github.com/stormpath/express-stormpath).\n\n* Added support for the registration view model ([#119](https://github.com/stormpath/stormpath-sdk-angularjs/pull/119))\n\n  This allows you to customize the registration form using the Stormpath Express configuration: <https://docs.stormpath.com/nodejs/express/latest/registration.html#creating-custom-fields>\n\n* Added support for the login view model ([#118](https://github.com/stormpath/stormpath-sdk-angularjs/pull/118))\n\n  This allows you to customize the login form using the Stormpath Express configuration: <https://docs.stormpath.com/nodejs/express/latest/login.html#form-customization>\n\n* Changed logout request to use POST ([#117](https://github.com/stormpath/stormpath-sdk-angularjs/pull/117))\n* Added support for new error structure ([#114](https://github.com/stormpath/stormpath-sdk-angularjs/pull/114))\n* Added X-Stormpath-Agent header to requests ([#107](https://github.com/stormpath/stormpath-sdk-angularjs/pull/107))\n\n# 0.9.0\n\n* Adding support for ngRoute.  Please see the API Documentation and the new\n  `ng-route-app` in the examples folder!\n\n* Bug fixed: you could navigate to the login form, even when logged in.\n\n* Updating `express-stormpath` versions in example projects.\n\n# 0.8.2\n\n* Bug fixed: `stormpath-sdk-angularjs` now exports 'stormpath' instead of 'ui.router'\n\n# 0.8.1\n\n* Fixed bug that displayed social login titles without any social login providers\n* Updated grunt-html2js to version 0.3.5\n* Updated grunt-contrib-clean to version 0.7.0\n* Updated grunt-contrib-uglify to version 0.10.1\n* Removed dist folder from the ignored file so we can use this lib with webpack or browserify\n\n# 0.8.0\n\n* Added support for social login with Google and Facebook (requires use of\n  [Express-Stormpath][] as your backend)\n\n# 0.7.2\n\n**Released on October 26th, 2015**\n\n* Updating `grunt-contrib` dependencies\n\n# 0.7.1\n\n**Released on October 8th, 2015**\n\nFixed the [ifUserInGroup][] and [ifUserNotInGroup][] directives to expect the\nnew data format (expanded `account.groups`) from the `/me` route\n\n# 0.7.0\n\n### ! ** Many Breaking Changes ** !\n\nThis library has been upgraded to conform to our framework specification,\nthis means that many of the endpoints and default URLs have changed.\n\nIf you have built a server integration by hand, you will need to read this changelog\nto know which URLs and HTTP responses that you will need to change.\n\nIf you are using [Stormpath Express SDK][], that module is being deprecated. You\nwill need to start using [Express-Stormpath][] if you want to use this and\nfuture versions of this Angular SDK.  We suggest that you read the [Server\nConfiguration][] section of our [Yeoman Guide][], it will show you the new way\nof initializing [Express-Stormpath][] and attaching it to your application\n\n#### Login Changes\n\nThe login feature now uses `/login` as the location where posts the login\nform.  Previously this was `/oauth/token`.  This can be configured with the\n`AUTHENTICATION_ENDPOINT` property in `STORMPATH_CONFIG`\n\n#### User Context Changes\n\nThis SDK now uses the `/me` URL to determine the context of the current user.\nPreviously this was `/api/users/current`.  This can be configured with the\n`CURRENT_USER_URI` property in `STORMPATH_CONFIG`\n\n#### Email Verification Changes\n\nThis SDK now uses the `/verify` URL to consume email verification tokens.\nPreviously this was `/api/emailVerificationTokens`.  This can be configured with the\n`EMAIL_VERIFICATION_ENDPOINT` property in `STORMPATH_CONFIG`\n\nThe same URL, `/verify`, is now used to request a re-send of a verification email.\nPOST a JSON body with an `email` property to trigger this action.  Previously\nthis was `/api/verificationEmails` and the `RESEND_EMAIL_VERIFICATION_ENDPOINT`\nproperty has been removed from `STORMPATH_CONFIG`.\n\n#### Password Reset Changes\n\nThis SDK now uses `/forgot` to request a password reset email, POST a JSON body\nto this endpoint with an `email` property to trigger this action.  Previously\nthis was `/api/passwordResetTokens` and the\n`PASSWORD_RESET_TOKEN_COLLECTION_ENDPOINT` property has been removed from\n`STORMPATH_CONFIG`.  The new property is `FORGOT_PASSWORD_ENDPOINT`\n\nThe `/change` URL is now used to POST a new password, with a valid `sptoken`.\nPreviously this feature was supported with the `/api/passwordResetTokens` URL\nand the `PASSWORD_RESET_TOKEN_COLLECTION_ENDPOINT` property has been removed\nfrom `STORMPATH_CONFIG`.  The new property is `CHANGE_PASSWORD_ENDPOINT`\n\nThe default login form now links to the forgot password flow via an href link\nto `/forgot`. Previously it was using a UI Router state name of\n`passwordResetRequest`\n\n#### Registration Changes\n\nThe SDK now uses `/register` to POST data for a new account, previously this\nwas `/api/users` and the `USER_COLLECTION_URI` property has been removed from\n`STORMPATH_CONFIG`.  The new property is `REGISTER_URI`.\n\nThe callback for `$user.create()` will now give you the entire account object.\nPreviously it gave you a truthy value that would indicate if the account required\nemail verification.  Now that the entire account object is passed, you need to\ninspect the account object's `status` property to see if it is `UNVERIFIED`.\n\nIf your registration form is passing data for the new account's custom data\nobject, you will need to change your `ng-model` references from\n`formModel.customData.<FIELD>` to `formModel.<FIELD>`.  We will automaticaly\nfind the properties that are not part of the base account object, and place them\non the custom data object for you.\n\n#### Error responses\n\nThis SDK now expects any HTTP call which results in a `4xx` error to supply an\n`error` property on the JSON body of the response.  Previously it expected\nan `errorMessage` property\n\n\n# 0.6.0\n\n### Breaking Changes\n\nStormpath's password reset API accepts email address only,\nnot username.  This library was allowing a username to be\nsent, but that will not work.  If using the [Stormpath Express SDK]\nyou will also need to update that library to `>=0.5.0`\n\n# 0.5.5\n\nFix a redirect loop in the state change interceptor\n\n# 0.5.4\n\nFix an undefined attribute bug with the group membership directives\n\n# 0.5.3\n\nAdding social login support.  **NOTE**: this is overloading oauth grant_type,\nand we will change this API in the future so use with this disclaimer.\n\n### Bug Fixes\n\n# 0.5.2\n\n### Improvements\n\n* Remove un-used `$cookieStore` dependency\n\n### Bug Fixes\n\n* The config option FORM_CONTENT_TYPE was not being used to modify\n  the body of the request (only the content-type header)\n\n# 0.5.1\n\n### Bug Fixes\n\nThe `defaultPostLoginState` option was not being used by the SDK, but now it is!\n\n# 0.5.0\n\n### New Features\n\nXHR requests now set the `withCredentials` option to `true`, allowing you to\nmake cross-domain requests that will send the `access_token` and `XSRF-TOKEN`\ncookies.  Your server must respond with the necessary\n[Cross-Origin-Resource-Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) headers.\nIf you are using our Express SDK this is done by specifying\n[Allowed Origins on spConfig](https://github.com/stormpath/stormpath-sdk-express#allowedOrigins)\n\n# 0.4.1\n\n### New Features\n\nThe UI Router integration now accepts a `forbiddenState` option, this is the\nstate we will send the user to if they are unauthorized for a given state.\nThis is useful if you want to show a default \"Forbidden\" view in these\nsituations.\n\nAdded documentation for the [$stateChangeUnauthenticated] and\n[$stateChangeUnauthorized] events!\n\n# 0.4.0\n\n### Breaking Changes\n\nThe [ifUserInGroup] and [ifUserNotInGroup] directives now requires you to pass\neither a string expression or a reference to a scope variable.  I.E. this will\nnow throw a parse exception unless `admin` is a reference to a scope property:\n\n```html\n<div if-user-in-group=\"admin\">Hello, Administrator</div>\n```\n\nIt should be re-written to be a string expression with quotes:\n\n```html\n<div if-user-in-group=\"'admin'\">Hello, Administrator</div>\n```\n\n## New Features\n\nThe [ifUserInGroup] and [ifUserNotInGroup] directives now support regular\nexpressions :)\n\nSee the documentation of [ifUserInGroup] for more information\n\n# 0.3.0\n\n### Breaking Changes\n\n* The `logout` directive is renamed to\n[`spLogout`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spLogout:spLogout)\n\n* The registration form now uses property names of\n`givenName` and `surname`, instead of `firstName` and `lastName`\n\n* Form submissions now use `application/x-www-form-urlencoded` as the Content Type.\nYour server needs to negotiate this type, if you are using our server SDKs this happens\nfor you.  If you wish to continue using `application/json` as the Content\nType you can define `STORMPATH_CONFIG.FORM_CONTENT_TYPE='application/json'` in a\nconfig block\n\n## Deprecation Notices\n\n* [`whileResolvingUser`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.whileResolvingUser:while-resolving-user)\nis deprecatead.  Use\n[`ifUserStateKnown`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserStateKnown:ifUserStateKnown)\ninstead.\n\n### New Features\n\n* **Custom Data on Registration**.  You can now pass custom data during\nregistration, simply reference `formModel.customData.myCustomProperty` in your\n`ng-model` directive.  This is only possible if you are supplying a custom\ntemplate to the directive.  See the\n[`spRegistrationForm`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spRegistrationForm:spRegistrationForm)\ndirective for more detail.\n\n* **Group-Based Access Control**.  This can now control access to UI Routes,\nbased on group membership.  See\n[`SpStateConfig`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.SpStateConfig:SpStateConfig)\nfor examples.  We've also introduced the\n[`ifUserInGroup`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserInGroup:ifUserInGroup)\nand\n[`ifUserNotInGroup`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserNotInGroup:ifUserNotInGroup)\ndirectives.\n\n### Bug Fixes\n\n* [`whileResolvingUser`](https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.whileResolvingUser:while-resolving-user)\nwould break after logout (user state was not properly reflected after logout)\n\n[Stormpath Express SDK]: https://github.com/stormpath/stormpath-sdk-express\n[$stateChangeUnauthenticated]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.$stormpath#events_$statechangeunauthenticated\n[$stateChangeUnauthorized]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.$stormpath#events_$statechangeunauthorized\n[ifUserInGroup]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserInGroup:ifUserInGroup\n[ifUserNotInGroup]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserNotInGroup:ifUserNotInGroup\n[Express-Stormpath]: https://github.com/stormpath/express-stormpath\n[Server Configuration]: http://docs.stormpath.com/angularjs/guide/protect_api.html\n[Yeoman Guide]: http://docs.stormpath.com/angularjs/guide/\n[Stormpath Client API]: https://docs.stormpath.com/client-api/product-guide/latest/index.html"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution Guide\n\nWe love pull requests!\n\nHere are a few things you'll need to know if you want to make a contribution to\nthis library.\n\n### Development Workflow\n\nAll modifications should happen to the source files in the `src/` directory, not\nthe files minified in the `dist/` directory.  The latter is used for keeping a\nminified version of the current, tagged build.  We give this to\n[Bower](http://bower.io).\n\nYou can submit a PR after modifying the source files.  We will publish a new\nversion in `dist/` when we are ready to cut a new release.\n\n### API Documentation\n\nThe API documentation is auto-generated from the the JS-Doc style comments\nthat you find in the `src/` files.  Do not edit files in `dist/`.\n\nYou can regenerate the API docs by running `grunt docs`.  If you want to\nsee your changes as you edit them you can use `grunt serve` to start a\nlivereload server that will reload your changes as you make them.\n\nWhen editing the JS Doc comments, please follow this order for tags:\n\n```\n@ngdoc\n@name\n@methodOf (or eventOf, etc)\n@eventType (if applicable)\n@param\n@returns\n@description\n@example\n```\n\nAfter you have made your edits, commit your changes and make a pull request.\n\nAnd put a newline before and after the line that includes the tag.\n\n### Product Guide Documentation\n\nThe source files for the product guide are located in the `docs/source`\ndirectory.  The format is RST and they are compiled by Sphinx.\n\nTo work with the product guide, run `grunt guide`.  This will start a livereload\nserver which reloads the documents as you edit them.\n\nAfter you have made your edits, commit the changes to the RST files and make\na pull request."
  },
  {
    "path": "Gruntfile.js",
    "content": "// Generated on 2015-01-02 using generator-angular-fullstack 2.0.13\n'use strict';\n\nmodule.exports = function (grunt) {\n  // Load grunt tasks automatically\n  require('load-grunt-tasks')(grunt);\n\n\n  grunt.initConfig({\n    builddir: '.tmp/build',\n    tmpdir: '.tmp',\n    srcDir: './src',\n    src: '<%= srcDir %>/**/*.js',\n    pkg: grunt.file.readJSON('package.json'),\n    buildtag: '-dev-' + grunt.template.today('yyyy-mm-dd'),\n    meta: {\n      banner: '/**\\n' +\n        ' * <%= pkg.name %>\\n' +\n        ' * Copyright <%= pkg.author %> '+grunt.template.today('yyyy')+'\\n' +\n        ' * <%= pkg.description %>\\n' +\n        ' * @version v<%= pkg.version %><%= buildtag %>\\n' +\n        ' * @link <%= pkg.homepage %>\\n' +\n        ' * @license <%= pkg.license %>\\n' +\n        ' */'\n    },\n    clean: {\n      ngdocs: '<%= tmpdir %>/site/**/*'\n    },\n    replace: {\n      dist: {\n        options: {\n          patterns: [\n            {\n              match: 'PACKAGE_VERSION',\n              replacement: '<%= pkg.version %>'\n            },\n            {\n              match: 'PACKAGE_NAME',\n              replacement: '<%= pkg.name %>'\n            }\n          ]\n        },\n        files: [\n          {expand: true, flatten: true, src: ['<%= builddir %>/<%= pkg.name %>*.js'], dest: '<%= builddir %>'}\n        ]\n      }\n    },\n    concat: {\n      options: {\n        banner: '<%= meta.banner %>\\n\\n'+\n                '/* commonjs package manager support (eg componentjs) */\\n'+\n                'if (typeof module !== \"undefined\" && typeof exports !== \"undefined\" && module.exports === exports){\\n'+\n                '  module.exports = \\'stormpath\\';\\n'+\n                '}\\n\\n'+\n                '(function (window, angular, undefined) {\\n',\n        footer: '})(window, window.angular);'\n      },\n      build: {\n        src: '<%= src %>',\n        dest: '<%= builddir %>/<%= pkg.name %>.js'\n      }\n    },\n    uglify: {\n      options: {\n        banner: '<%= meta.banner %>\\n'\n      },\n      build: {\n        files: {\n          '<%= builddir %>/<%= pkg.name %>.min.js': ['<banner:meta.banner>', '<%= concat.build.dest %>'],\n          '<%= builddir %>/<%= pkg.name %>.tpls.min.js': ['<banner:meta.banner>', '<%= builddir %>/<%= pkg.name %>.tpls.js']\n        }\n      }\n    },\n    release: {\n      files: ['<%= pkg.name %>.js', '<%= pkg.name %>.min.js'],\n      src: '<%= builddir %>',\n      dest: 'release'\n    },\n    jshint: {\n      all: ['Gruntfile.js', 'src/*.js', '<%= builddir %>/<%= pkg.name %>.js'],\n      options: {\n        eqnull: true\n      }\n    },\n    watch: {\n      gruntfile: {\n        files: ['Gruntfile.js']\n      },\n      ngdocs: {\n        files: ['<%= src %>','ngdoc_assets/**/*'],\n        tasks: ['docs'],\n        options: {\n          livereload: 35730,\n          spawn: false\n        }\n      },\n      guide: {\n        files: ['docs/source/*.rst','docs/source/_themes/stormpath/*/**'],\n        tasks: ['shell:guide'],\n        options: {\n          livereload: 35731,\n          spawn: false\n        }\n      },\n      src: {\n        files: ['<%= src %>'],\n        tasks: ['build']\n      },\n      develop: {\n        files: ['<%= srcDir %>/*.{js,html}'],\n        tasks: ['dist']\n      }\n    },\n    connect: {\n      ngdocs: {\n        options: {\n          port: 9001,\n          base: '<%= tmpdir %>/site',\n          livereload: 35730\n        }\n      },\n      guide: {\n        options: {\n          port: 9002,\n          livereload: 35731,\n          base: ['docs/build/html']\n        }\n      }\n    },\n    open: {\n      docs: {\n        url: 'http://localhost:<%= connect.ngdocs.options.port %>'\n      },\n      guide:{\n        url: 'http://localhost:<%= connect.guide.options.port %>'\n      }\n    },\n    ngdocs: {\n      options: {\n        dest: '<%= tmpdir %>/site',\n        scripts: [\n          'angular.js'\n        ],\n        styles: [ 'ngdoc_assets/stormpath-angular.css' ],\n        html5Mode: false,\n        title: 'stormpath-sdk-angularjs',\n        startPage: '/api',\n        navTemplate: 'ngdoc_assets/nav.html'\n      },\n      api: {\n        src: ['<%= src %>','ngdoc_assets/index.ngdoc'],\n        title: 'API Reference',\n        api: true\n      }\n    },\n    copy: {\n      dist: {\n        files:[{\n          expand: true,\n          flatten: true,\n          src: '<%= builddir %>/*',\n          dest: 'dist/'\n        }]\n      }\n    },\n    html2js: {\n      options: {\n        module: 'stormpath.templates',\n        fileHeaderString: '<%= meta.banner %>\\n\\n'+\n                          '/* commonjs package manager support (eg componentjs) */\\n'+\n                          'if (typeof module !== \"undefined\" && typeof exports !== \"undefined\" && module.exports === exports){\\n'+\n                          '  module.exports = \\'stormpath.templates\\';\\n'+\n                          '}\\n\\n'+\n                          '(function (window, angular, undefined) {\\n',\n        fileFooterString: '})(window, window.angular);',\n        htmlmin: {\n          collapseBooleanAttributes: false,\n          collapseWhitespace: true,\n          removeAttributeQuotes: true,\n          removeComments: true,\n          removeEmptyAttributes: false,\n          removeRedundantAttributes: true,\n          removeScriptTypeAttributes: false,\n          removeStyleLinkTypeAttributes: false\n        }\n      },\n      main: {\n        src: ['src/**/*.tpl.html'],\n        dest: '<%= builddir %>/<%= pkg.name %>.tpls.js'\n      }\n    },\n    shell: {\n      guide: {\n        command: 'make clean && make html',\n        options:{\n          execOptions: {\n            cwd: 'docs/'\n          }\n        }\n      }\n    }\n  });\n\n  grunt.registerTask('docs', 'Builds the Guide and ngDocs for deployment',function () {\n    grunt.task.run(\n      ['clean:ngdocs','ngdocs','shell:guide']\n    );\n  });\n\n  grunt.registerTask('serve',\n    'Serves the API documentation, and live reloads as you edit it',\n    ['ngdocs','connect:ngdocs','open:docs','watch:ngdocs']\n  );\n\n  grunt.registerTask('build', 'Perform a normal build', ['concat', 'html2js','uglify','docs']);\n\n  grunt.registerTask('dist', 'Perform a distribution', ['build', 'replace:dist', 'copy:dist']);\n\n  grunt.registerTask('develop',\n    'Build source and distribution, useful if you are modifying this module as a linked modue while developging another module',\n    ['watch:develop']\n  );\n\n  grunt.registerTask('guide',\n    'Serve and livereload the Guide from the docs/ folder',\n    ['connect:guide','open:guide','watch:guide']\n  );\n};\n"
  },
  {
    "path": "LICENSE",
    "content": "\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2015 Stormpath, Inc.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "OLD-README.md",
    "content": "# Stormpath is Joining Okta\nWe are incredibly excited to announce that [Stormpath is joining forces with Okta](https://stormpath.com/blog/stormpaths-new-path?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement). Please visit [the Migration FAQs](https://stormpath.com/oktaplusstormpath?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement) for a detailed look at what this means for Stormpath users.\n\nWe're available to answer all questions at [support@stormpath.com](mailto:support@stormpath.com).\n\n# Stormpath AngularJS SDK\n\n[![NPM Version](https://img.shields.io/npm/v/stormpath-sdk-angularjs.svg?style=flat)](https://npmjs.org/package/stormpath-sdk-angularjs)\n[![NPM Downloads](http://img.shields.io/npm/dm/stormpath-sdk-angularjs.svg?style=flat)](https://npmjs.org/package/stormpath-sdk-angularjs)\n[![Bower Version](https://img.shields.io/bower/v/stormpath-sdk-angularjs.svg?style=flat)](https://bower.io)\n[![Build Status](https://img.shields.io/travis/stormpath/stormpath-sdk-angularjs.svg?style=flat)](https://travis-ci.org/stormpath/stormpath-sdk-angularjs)\n\nThis module provides services and directives for AngularJS that will allow you to solve common user management tasks using [Stormpath](https://stormpath.com/), such as *login* and *signup*.\n\n*Stormpath is a User Management API that reduces development time with instant-on, scalable user infrastructure. Stormpath's intuitive API and expert support make it easy for developers to authenticate, manage and secure users and roles in any application.*\n\n* [Getting Started](#getting-started)\n* [Documentation](#documentation)\n* [Example](#example)\n* [Help](#help)\n* [Contributing](#contributing)\n* [License](#license)\n\n## Getting Started\n\nFollow these steps to add Stormpath user authentication to your AngularJS app.\n\n1. **Install or Download the Stormpath Angular SDK**\n\n  If you are using Bower or NPM, you can install this module with the respective command:\n\n  ```\n  npm install stormpath-sdk-angularjs --save\n  ```\n\n  ```\n  bower install stormpath-sdk-angularjs --save\n  ```\n\n  If you are not using a package manager, you can download the latest source from our Github CDN by using these links:\n\n  * [stormpath-sdk-angularjs.min.js](https://raw.githubusercontent.com/stormpath/stormpath-sdk-angularjs/master/dist/stormpath-sdk-angularjs.min.js)\n  * [stormpath-sdk-angularjs.tpls.min.js](https://raw.githubusercontent.com/stormpath/stormpath-sdk-angularjs/master/dist/stormpath-sdk-angularjs.tpls.min.js)\n\n  Then include them in your *index.html* file:\n\n  ```html\n  <script src=\"stormpath-sdk-angularjs.min.js\"></script>\n  <script src=\"stormpath-sdk-angularjs.tpls.min.js\"></script>\n  ```\n\n2. **Add the Module to Your App's Dependencies**\n\n  Add the `stormpath` module and templates to your app's dependencies in *app.js*:\n\n  ```javascript\n  var app = angular.module('myApp', [..., 'stormpath', 'stormpath.templates']);\n  ```\n\n3. **Configure Stormpath**\n\n  The Angular SDK leverages the [Stormpath Client API][] for its authentication needs. Login to your Stormpath Tenant, and find your Client API domain (inside your application's policy section).  Add your Client API domain as the `ENDPOINT_PREFIX` setting, via your `.config()` function:\n\n  ```javascript\n  angular.module('myApp', [..., 'stormpath', 'stormpath.templates'])\n    .config(function (STORMPATH_CONFIG) {\n\n      // Specify your Client API domain here:\n\n      STORMPATH_CONFIG.ENDPOINT_PREFIX = 'https://{{clientApiDomainName}}';\n    });\n  ```\n  You will need to tell Stormpath where your front-end application is running, by adding its domain to the list of Authorized Origin URIs on your Stormpath Application. This can be done from the Stormpath Admin Console. For example, if you are developing on a local sever that runs your front-end app at `http://localhost:3000`, you need to add that URI to the list\n\n  If this is not done, you will see the error `Origin 'http://localhost:3000' is therefore not allowed access.` in the browser error log.\n\n  If you will be using social login, you will also need to add this URI to the list of Authorized Callback URIs, otherwise you will see the error `Specified redirect_uri is not in the application's configured authorized callback uri's.` when you attempt social login.\n\n\n4. **Configure Routing**\n\n  In your app's `run()` block, configure the login state and the default state after login.\n\n  For `ngRouter`:\n\n  ```javascript\n  angular.module('myApp')\n    .run(function($stormpath){\n      $stormpath.ngRouter({\n        forbiddenRoute: '/forbidden',\n        defaultPostLoginRoute: '/home',\n        loginRoute: '/login'\n      });\n    });\n  ```\n\n  For `uiRouter`:\n\n  ```javascript\n  app.run(function($stormpath){\n    $stormpath.uiRouter({\n      loginState: 'login',\n      defaultPostLoginState: 'home'\n    });\n  });\n  ```\n\n  Set `loginState` to your login state. If you don't have one, create one.\n  Set `defaultPostLoginState` to your default state after login.\n\n\n\n5. **Insert the Login and Registration Forms**\n\n   You can use the [`sp-login-form`][] and [`sp-registration-form`][] directives to inject these default forms into your application, you should put this in the views/states where you want them to appear:\n\n   ```html\n   <div sp-login-form></div>\n   ```\n\n   ```html\n   <div sp-registration-form></div>\n   ```\n\n    </p>\n    These forms will read their configuration from the Client API and allow you to login or register for your application.\n    You should now be able to use these forms to login to your application.\n\n6. **Add Login and Logout Links**\n\n  Use the [`sp-logout`][] directive to end the session:\n\n  ```html\n  <a ui-sref=\"main\" sp-logout>Logout</a>\n  ```\n\n  For the login link, just point the user to your login state:\n\n  ```html\n  <a ui-sref=\"login\">Login</a>\n  ```\n\n7. **Hide Elements When Logged In**\n\n  Use the [`if-user`][] directive:\n\n  ```html\n  <a ui-sref=\"main\" sp-logout if-user>Logout</a>\n  ```\n\n8. **Hide Elements When Logged Out**\n\n  Use the [`if-not-user`][] directive:\n\n  ```html\n  <a ui-sref=\"login\" if-not-user>Login</a>\n  ```\n\n9. **Protect Your States**\n\n  On all states that you want to protect, add:\n\n  ```javascript\n  sp: {\n    authenticate: true\n  }\n  ```\n\n  For `ngRouter`:\n\n  ```javascript\n  angular.module('myApp')\n    .config(function ($routeProvider) {\n      $routeProvider\n        .when('/profile', {\n          templateUrl: 'app/profile/profile.html',\n          controller: 'ProfileCtrl',\n          sp: {\n            authenticate: true\n          }\n        });\n    });\n  ```\n\n  For `uiRouter`:\n\n  ```javascript\n  angular.module('myApp')\n    .config(function ($stateProvider) {\n      $stateProvider\n        .state('profile', {\n          url: '/profile',\n          templateUrl: 'app/profile/profile.html',\n          controller: 'ProfileCtrl',\n          sp: {\n            authenticate: true\n          }\n        });\n    });\n  ```\n\n\n10. **Login!**\n\n  That's it!  You just added user authentication to your app with Stormpath. See the [API Documentation][] for further information on how Stormpath can be used with your AngularJS app.\n\n  Looking for social login?  Simply configure the directories in your Stormpath tenant, and the buttons will automatically appear in the login form.  For more reading, please see the [Social Login Product Guide][].\n\n11. **Making Authenticated Requests**\n\n  Once you are able to successfully authenticate (log in) from your application, you will want to authorize access to API endpoints on your server.  The Angular SDK provides methods for getting the current authenticated access token, and using it to authenticate requests.\n\n  Imagine you have an API on your server, such as `http://localhost:3000/api/subscription`, and you want to authorize requests to this endpoint and know who the user is.\n\n  If you want to manually construct a request, using the `$http` library, you can use our access token getter to add the access token to the request:\n\n  ```javascript\n  StormpathOAuthToken.getAccessToken()\n    .then(function(accessToken){\n      $http({\n        url: 'http://localhost:3000/api/subscription',\n        method: 'GET',\n        headers: {\n          Authorization: 'Bearer ' + accessToken\n        }\n      });\n    })\n    .catch(function() {\n      // No access token, the user is not logged in\n    });\n  ```\n\n  If you don't want to manually add the access token to every request, you can white-list URLs by expression and the Angular SDK will automatically add this token to all requests that have a matching URL:\n\n  ```javascript\n  angular.module('myApp', [..., 'stormpath', 'stormpath.templates'])\n    .config(function (STORMPATH_CONFIG) {\n\n      // Automatically add access token to all /api requests\n\n      STORMPATH_CONFIG.AUTO_AUTHORIZED_URIS.push(new RegExp('/api'));\n    });\n  ```\n\n12. **Authorizing Requests Server-Side**\n\n  Once your app has made the request with the access token, your server will need to read the token and make an authorization decision.  We provide SDKs for your backend server that make this easy.  Please follow one of the following links for a language-specific or framework-specific guide:\n\n  **Java**\n\n  Spring Boot developers should make use of our Spring Boot plugin, and see the [Token Management Documentation](https://docs.stormpath.com/java/spring-boot-web/tutorial.html#token-management).\n\n  **.NET**\n\n  ASP.NET developers can leverage our [ASP.NET](https://docs.stormpath.com/dotnet/aspnet/latest/) and [ASP.NET Core](https://docs.stormpath.com/dotnet/aspnetcore/latest/) libraries to achieve authorization in their applications, please see the Authorization section of each guide.\n\n  **Node.js**\n\n  Express developers can use our [Express-Stormpath](https://docs.stormpath.com/nodejs/express/latest/) library to easily authenticate requests with access tokens and make authorization decisions, please see the [Token Authentication](https://docs.stormpath.com/nodejs/express/latest/authentication.html#token-authentication) documentation.\n\n  Node applications can generically use the [Stormpath Node SDK](https://docs.stormpath.com/nodejs/jsdoc/) to validate tokens, using the [JwtAuthenticator](https://docs.stormpath.com/nodejs/jsdoc/JwtAuthenticator.html).\n\n  **PHP**\n\n  Laravel developers can use our <a href=\"https://docs.stormpath.com/php/laravel/latest/index.html\">Stormpath-Laravel</a> or [Stormpath-Lumen](https://docs.stormpath.com/php/lumen/latest/index.html) libraries and their respective `stormpath.auth` middleware to authenticate requests, please see the User Data section of the documentation for each library.\n\n  **Other**\n\n  Don't see your environment listed?  Not a problem!  Our access tokens are simple JWTs, that can be validated with most generic JWT validation libraries.  Our product guide can walk you through the process, [Validating an Access Token](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#validating-an-access-token\").\n\n  Need more assistance? Feel free to contact our support channel, details are below.\n\n## Documentation\n\nFor all available directives and services, see the [API Documentation][].\n\n## Example\n\nSee the [example app][] in this repository for an example application that uses\nYeoman as it's boilerplate.\n\nFor a simplified example that does not use a boilerplate system, please see\nthis repository:\n\n[Stormpath Angular + Express Fullstack Sample Project](https://github.com/stormpath/express-stormpath-angular-sample-project)\n\nIf you are hosting your API on a different domain than your Angular application,\nplease see the [CORS example app][] in this repository.\n\n## Browserify\n\nThis module can be used with Browserify.  Please add the following lines to your\n`package.json` file:\n\n```json\n\"browser\": {\n  \"stormpath\": \"./node_modules/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.js\",\n  \"stormpath.templates\": \"./node_modules/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.tpls.js\"\n}\n```\n\nYou should also install the package `angular-ui-router`, as our library\ncurrently depends on it.\n\nThen in your application you can use `require` to require our modules:\n\n```javascript\nvar app = angular.module('todoApp', [\n  require('angular-ui-router'),\n  require('stormpath'),\n  require('stormpath.templates')\n]);\n```\n\n## Support\n\nWe're here to help if you get stuck.  There are several ways that you an get in\ntouch with a member of our team:\n\n* Send an email to [support@stormpath.com](mailto:support@stormpath.com)\n* Open a Github Issue on this repository.\n* Join us on our Slack channel: [https://talkstormpath.shipit.xyz/](https://talkstormpath.shipit.xyz/)\n\n[Stormpath AngularJS SDK]: https://github.com/stormpath/stormpath-sdk-angularjs\n[Stormpath Product Guide]: https://docs.stormpath.com/rest/product-guide/latest/\n[Stormpath React SDK]: https://github.com/stormpath/stormpath-sdk-react\n[express-stormpath]: https://docs.stormpath.com/nodejs/express/latest/\n\n## Contributing\n\nFound something you want to change? Please see the [Contribution Guide](CONTRIBUTING.md),\nwe love your input!\n\n## License\n\nApache 2.0, see [LICENSE](LICENSE).\n\n[`if-user`]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUser:ifUser\n[`if-not-user`]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifNotUser:ifNotUser\n[`sp-login-form`]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spLoginForm:spLoginForm\n[`sp-logout`]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spLogout:spLogout\n[`sp-registration-form`]: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spRegistrationForm:spRegistrationForm\n[example app]: https://github.com/stormpath/stormpath-sdk-angularjs/tree/master/example/dashboard-app\n[API Documentation]: https://docs.stormpath.com/angularjs/sdk/\n[Server Integration Guide]: https://docs.stormpath.com/angularjs/sdk/#/server\n[express-stormpath]: https://github.com/stormpath/express-stormpath\n[Stormpath SPA Development Server]: https://github.com/stormpath/stormpath-spa-dev-server\n[UI-Router]: https://github.com/angular-ui/ui-router\n[Yeoman Guide]: https://docs.stormpath.com/angularjs/guide\n[support center]: https://support.stormpath.com\n[CORS example app]: https://github.com/stormpath/stormpath-sdk-angularjs/tree/master/example/cors-app\n[Stormpath Client API]: https://docs.stormpath.com/client-api/product-guide/latest/index.html\n[Social Login Product Guide]: https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#how-social-authentication-works\n"
  },
  {
    "path": "README.md",
    "content": "# Stormpath is Joining Okta\nWe are incredibly excited to announce that [Stormpath is joining forces with Okta](https://stormpath.com/blog/stormpaths-new-path?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement). Please visit [the Migration FAQs](https://stormpath.com/oktaplusstormpath?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement) for a detailed look at what this means for Stormpath users.\n\nWe're available to answer all questions at [support@stormpath.com](mailto:support@stormpath.com).\n\n## What does this mean for developers who are using this library?\n\n* If you have upgraded to the 2.x series from 1.x, you should downgrade to 1.1.1.  Why?  The 2.x series depends on the Stormpath Client API, which will not be migrated to the Okta platform.\n* When downgrading to 1.1.1 you will need to use one of our backend framework integrations to serve the APIs that the 1.x series depends on.\n* These backend integrations are being patched to work with Okta:\n - [Java Spring](https://docs.stormpath.com/java/#tab3)\n - [Java Spring Boot](https://docs.stormpath.com/java/#tab1)\n - [Node Express](https://docs.stormpath.com/nodejs/)\n - [ASP.NET 4.x](https://docs.stormpath.com/dotnet/#tab3)\n - [ASP.NET Core](https://docs.stormpath.com/dotnet/#tab2)\n* If you are using the Express integration, please see the [Express-Stormpath Angular Sample Project][], it can be used to test your migration to Okta.\n\n# README\n\nIf you are actively using this library, you can find the old readme in [OLD-README.md](OLD-README.md). It is not possible to register for new Stormpath tenants at this time, so you must already have a Stormpath tenant if you wish to use this library during the migration period.\n\n[Express-Stormpath Angular Sample Project]: https://github.com/stormpath/express-stormpath-angular-sample-project\n"
  },
  {
    "path": "TROUBLESHOOTING.md",
    "content": "# Troubleshooting\n\nThis document contains a list of common problems that you may run into while\nworking with this library.\n\n#### \"Invalid username or password.\" when using Social Login\n\nIf you are using [express-stormpath][] as your back-end you may see this error\nwhen attempting a social login.  This happens if the Body Parser module is\nconfigured before the Express Stormpath module.  If you must do this, please\nensure that you are enabling the extended option for the parser:\n\n```javascript\napp.use(bodyParser.urlencoded({ extended: true }));\n```\n\nThis issue is being tracked here:\n\nhttps://github.com/stormpath/express-stormpath/issues/194\n\n[express-stormpath]: https://github.com/stormpath/express-stormpath"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"stormpath-sdk-angularjs\",\n  \"version\": \"2.0.1\",\n  \"main\": [\n    \"dist/stormpath-sdk-angularjs.min.js\",\n    \"dist/stormpath-sdk-angularjs.tpls.min.js\"\n  ],\n  \"keywords\": [\n    \"stormpath\",\n    \"jwt\",\n    \"token\",\n    \"user\",\n    \"angular\",\n    \"token based authentication\",\n    \"login\",\n    \"password\",\n    \"registration\",\n    \"user management\"\n  ],\n  \"ignore\": [\n    \".tmp\",\n    \"build\",\n    \"docs\",\n    \"example\",\n    \"ngdoc_assets\",\n    \"src\"\n  ],\n  \"dependencies\": {\n    \"angular\": \">=1.2.*\"\n  }\n}\n"
  },
  {
    "path": "dist/stormpath-sdk-angularjs.js",
    "content": "/**\n * stormpath-sdk-angularjs\n * Copyright Stormpath, Inc. 2017\n * \n * @version v2.0.1-dev-2017-04-04\n * @link https://github.com/stormpath/stormpath-sdk-angularjs\n * @license Apache-2.0\n */\n\n/* commonjs package manager support (eg componentjs) */\nif (typeof module !== \"undefined\" && typeof exports !== \"undefined\" && module.exports === exports){\n  module.exports = 'stormpath';\n}\n\n(function (window, angular, undefined) {\n'use strict';\n\n/**\n * @ngdoc object\n *\n * @name stormpath.SpStateConfig:SpStateConfig\n *\n * @property {boolean} authenticate\n *\n * If `true`, the user must be authenticated in order to view this state.\n * If the user is not authenticated, they will\n * be redirected to the `login` state.  After they login, they will be redirected to\n * the state that was originally requested.\n *\n * @property {object} authorize\n *\n * An object that defines access control rules.  Currently, it supports a group-based\n * check.  See the example below.\n *\n * @property {boolean} waitForUser\n *\n * If `true`, delay the state transition until we know\n * if the user is authenticated or not.  This is useful for situations where\n * you want everyone to see this state, but the state may look different\n * depending on the user's authentication state.\n *\n *\n * @description\n *\n * The Stormpath State Config is an object that you can define on a UI Router\n * state.  Use this configuration to define access control for your routes, as\n * defined by UI Router.\n *\n * You will need to be using the UI Router module, and you need\n * to enable the integration by calling\n * {@link stormpath.$stormpath#methods_uiRouter $stormpath.uiRouter()} in your\n * application's config block.\n *\n * If you're using Angular's built-in `$routeProvider` instead of UI Router, please\n * use {@link stormpath.$stormpath#methods_ngRouter $stormpath.ngRouter()} instead.\n *\n * **NOTE:** Do not define this configuration on a abstract state, it must go on\n * the child state.  However, the controller of the abstract state will be\n * initialized AFTER any configuration rules of the child state have been met.\n *\n * # Support for `data.authorities`\n *\n * If you have used [JHipster](https://jhipster.github.io/) to generate your\n * project, you are likely using the `data.authorities` property to define\n * authorization for your views. This library will look for the `data.authorities`\n * property and apply the same logic as our own `sp.authorize` property.\n *\n * @example\n *\n * <pre>\n *\n * angular.module('myApp')\n *   .config(function ($stateProvider) {\n *\n *     // Wait until we know if the user is logged in before showing the homepage\n *     $stateProvider\n *       .state('main', {\n *         url: '/',\n *         sp: {\n *           waitForUser: true\n *         }\n *       });\n *\n *     // Require a user to be authenticated in order to see this state\n *     $stateProvider\n *       .state('secrets', {\n *         url: '/secrets',\n *         controller: 'SecretsCtrl',\n *         sp: {\n *           authenticate: true\n *         }\n *       });\n *\n *     // Require a user to be in the admins group in order to see this state\n *     $stateProvider\n *       .state('secrets', {\n *         url: '/admin',\n *         controller: 'AdminCtrl',\n *         sp: {\n *           authorize: {\n *             group: 'admins'\n *           }\n *         }\n *       });\n * });\n * </pre>\n *\n * If using JHipster generated code:\n *\n *  <pre>\n *     // Require a user to be in the admins group in order to see this state\n *     $stateProvider\n *       .state('secrets', {\n *         url: '/admin',\n *         controller: 'AdminCtrl',\n *         data: {\n *           authorities: ['admins']\n *         }\n *       });\n *  </pre>\n */\n\n /**\n * @ngdoc object\n *\n * @name stormpath.SpRouteConfig:SpRouteConfig\n *\n * @property {boolean} authenticate\n *\n * If `true`, the user must be authenticated in order to view this route.\n * If the user is not authenticated, they will\n * be redirected to the `login` route.  After they login, they will be redirected to\n * the route that was originally requested.\n *\n * @property {object} authorize\n *\n * An object that defines access control rules.  Currently, it supports a group-based\n * check.  See the example below.\n *\n * @property {boolean} waitForUser\n *\n * If `true`, delay the route transition until we know\n * if the user is authenticated or not.  This is useful for situations where\n * you want everyone to see this route, but the route may look different\n * depending on the user's authentication route.\n *\n *\n * @description\n *\n * The Stormpath Route Config is an object that you can define on a route.\n * Use this configuration to define access control for your routes, as\n * defined by the ngRoute module.\n *\n * You will need to be using the ngRoute module, and you need\n * to enable the integration by calling\n * {@link stormpath.$stormpath#methods_ngRouter $stormpath.ngRouter()} in your\n * application's config block.\n *\n * If you're using UI Router instead of Angular's built-in `$routeProvider`, please\n * use {@link stormpath.$stormpath#methods_uiRouter $stormpath.uiRouter()} instead.\n *\n * @example\n *\n * <pre>\n *\n * angular.module('myApp')\n *   .config(function ($routeProvider) {\n *     // Wait until we know if the user is logged in before showing the homepage\n *     $routeProvider\n *       .when('/main', {\n*         controller: 'MainCtrl',\n *         sp: {\n *           waitForUser: true\n *         }\n *       });\n *\n *     // Require a user to be authenticated in order to see this route\n *     $routeProvider\n *       .when('/secrets', {\n *         controller: 'SecretsCtrl',\n *         sp: {\n *           authenticate: true\n *         }\n *       });\n *\n *     // Require a user to be in the admins group in order to see this route\n *     $routeProvider\n *       .when('/secrets', {\n *         controller: 'AdminCtrl',\n *         sp: {\n *           authorize: {\n *             group: 'admins'\n *           }\n *         }\n *       });\n * });\n * </pre>\n */\nangular.module('stormpath', [\n  'stormpath.CONFIG',\n  'stormpath.utils',\n  'stormpath.auth',\n  'stormpath.userService',\n  'stormpath.viewModelService',\n  'stormpath.socialLogin',\n  'stormpath.oauth'\n])\n\n.factory('StormpathAgentInterceptor',['$isCurrentDomain', '$spHeaders', function($isCurrentDomain, $spHeaders){\n  function StormpathAgentInterceptor(){\n\n  }\n  /**\n   * Adds the X-Stormpath-Agent header, if the requested URL is on the same\n   * domain as the current document.\n   *\n   * @param  {Object} config $http config object.\n   * @return {Object} config $http config object.\n   */\n  StormpathAgentInterceptor.prototype.request = function(config){\n\n    var uriExpressions = [\n      '/change$',\n      '/forgot$',\n      '/login$',\n      '/logout$',\n      '/me$',\n      '/oauth/token$',\n      '/oauth/token$',\n      '/register$',\n      '/revoke$',\n      '/verify$'\n    ];\n\n    if (uriExpressions.some(function(expr){\n      return new RegExp(expr).test(config.url);\n    })) {\n      config.headers = angular.extend(config.headers, $spHeaders);\n    }\n\n    return config;\n  };\n\n  return new StormpathAgentInterceptor();\n}])\n.config(['$httpProvider',function($httpProvider){\n  $httpProvider.interceptors.push('StormpathAgentInterceptor');\n}])\n.provider('$stormpath', [function $stormpathProvider(){\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.$stormpath\n   *\n   * @description\n   *\n   * This service allows you to enable application-wide features of the library.\n   *\n   * At the moment the only feature is the UI Router integration, which is\n   * documented below.\n   */\n\n  this.$get = [\n    '$user', '$injector', 'STORMPATH_CONFIG', '$rootScope', '$location',\n    function stormpathServiceFactory($user, $injector, STORMPATH_CONFIG, $rootScope, $location) {\n      var $state;\n      var $route;\n\n      function StormpathService(){\n        var encoder = new UrlEncodedFormParser();\n        this.encodeUrlForm = encoder.encode.bind(encoder);\n\n        if ($injector.has('$state')) {\n          $state = $injector.get('$state');\n        }\n\n        if ($injector.has('$route')) {\n          $route = $injector.get('$route');\n        }\n\n        return this;\n      }\n      function stateChangeUnauthenticatedEvent(toState, toParams){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$stateChangeUnauthenticated\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toState The state that the user attempted to access.\n         *\n         * @param {Object} toParams The state params of the state that the user\n         * attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a UI state change is prevented,\n         * because the user is not logged in.\n         *\n         * Use this event if you want to implement your own strategy for\n         * presenting the user with a login form.\n         *\n         * To receive this event, you must be using the UI Router integration.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$stateChangeUnauthenticated',function(e,toState,toParams){\n         *     // Your custom logic for deciding how the user should login, and\n         *     // if you want to redirect them to the desired state afterwards\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHENTICATED,toState,toParams);\n      }\n      function stateChangeUnauthorizedEvent(toState,toParams){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$stateChangeUnauthorized\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toState The state that the user attempted to access.\n         *\n         * @param {Object} toParams The state params of the state that the user\n         * attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a UI state change is prevented,\n         * because the user is not authorized by the rules defined in the\n         * {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configuration}\n         * for the requested state.\n         *\n         * Use this event if you want to implement your own strategy for telling\n         * the user that they are forbidden from viewing that state.\n         *\n         * To receive this event, you must be using the UI Router integration.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$stateChangeUnauthorized',function(e,toState,toParams){\n         *     // Your custom logic for deciding how the user should be\n         *     // notified that they are forbidden from this state\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHORIZED,toState,toParams);\n      }\n      StormpathService.prototype.stateChangeInterceptor = function stateChangeInterceptor(config) {\n        $rootScope.$on('$stateChangeStart', function(e,toState,toParams){\n          var sp = toState.sp || {}; // Grab the sp config for this state\n          var authorities = (toState.data && toState.data.authorities) ? toState.data.authorities : undefined;\n\n          if((sp.authenticate || sp.authorize || (authorities && authorities.length)) && (!$user.currentUser)){\n            e.preventDefault();\n            $user.get().then(function(){\n              // The user is authenticated, continue to the requested state\n              if(sp.authorize || (authorities && authorities.length)){\n                if(authorizeStateConfig(sp, authorities)){\n                  $state.go(toState.name,toParams);\n                }else{\n                  stateChangeUnauthorizedEvent(toState,toParams);\n                }\n              }else{\n                $state.go(toState.name,toParams);\n              }\n            },function(){\n              // The user is not authenticated, emit the necessary event\n              stateChangeUnauthenticatedEvent(toState,toParams);\n            });\n          }else if(sp.waitForUser && ($user.currentUser===null)){\n            e.preventDefault();\n            $user.get().finally(function(){\n              $state.go(toState.name,toParams);\n            });\n          }\n          else if($user.currentUser && (sp.authorize || (authorities && authorities.length))){\n            if(!authorizeStateConfig(sp, authorities)){\n              e.preventDefault();\n              stateChangeUnauthorizedEvent(toState,toParams);\n            }\n          }else if(toState.name===config.loginState){\n            /*\n              If the user is already logged in, we will redirect\n              away from the login page and send the user to the\n              post login state.\n             */\n            if($user.currentUser!==false){\n              e.preventDefault();\n              $user.get().finally(function(){\n                if($user.currentUser && $user.currentUser.href){\n                  $state.go(config.defaultPostLoginState);\n                } else {\n                  $state.go(toState.name,toParams);\n                }\n              });\n            }\n          }\n        });\n      };\n\n      function authorizeStateConfig(spStateConfig, authorities){\n        var sp = spStateConfig;\n        if(sp && sp.authorize && sp.authorize.group) {\n          return $user.currentUser.inGroup(sp.authorize.group);\n        }else if(authorities){\n          // add support for reading from JHipster's data: { authorities: ['ROLE_ADMIN'] }\n          // https://github.com/stormpath/stormpath-sdk-angularjs/issues/190\n          var roles = authorities.filter(function(authority){\n            return $user.currentUser.inGroup(authority);\n          });\n          return roles.length > 0;\n        }else{\n          console.error('Unknown authorize configuration for spStateConfig',spStateConfig);\n          return false;\n        }\n      }\n\n      function routeChangeUnauthenticatedEvent(toRoute) {\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$routeChangeUnauthenticated\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toRoute The route that the user attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a route change is prevented,\n         * because the user is not logged in.\n         *\n         * Use this event if you want to implement your own strategy for\n         * presenting the user with a login form.\n         *\n         * To receive this event, you must be using the ngRoute module.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$routeChangeUnauthenticated', function(event, toRoute) {\n         *     // Your custom logic for deciding how the user should login, and\n         *     // if you want to redirect them to the desired route afterwards\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHENTICATED, toRoute);\n      }\n\n      function routeChangeUnauthorizedEvent(toRoute) {\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$routeChangeUnauthorized\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toRoute The route that the user attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a route change is prevented,\n         * because the user is not authorized by the rules defined in the\n         * {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configuration}\n         * for the requested route.\n         *\n         * Use this event if you want to implement your own strategy for telling\n         * the user that they are forbidden from viewing that route.\n         *\n         * To receive this event, you must be using the ngRoute module.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$routeChangeUnauthorized', function(event, toRoute) {\n         *     // Your custom logic for deciding how the user should be\n         *     // notified that they are forbidden from this route\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHORIZED, toRoute);\n      }\n\n      StormpathService.prototype.routeChangeInterceptor = function routeChangeInterceptor(config) {\n        function goToRoute(route) {\n          setTimeout(function() {\n            if (route.$$route.originalPath === $location.path()) {\n              $route.reload();\n            } else {\n              $location.path(route);\n            }\n          });\n        }\n\n        $rootScope.$on('$routeChangeStart', function(event, toRoute) {\n          if (!toRoute.$$route) {\n            return;\n          }\n\n          var sp = toRoute.$$route.sp || {}; // Grab the sp config for this route\n\n          if ((sp.authenticate || sp.authorize) && !$user.currentUser) {\n            event.preventDefault();\n\n            $user.get().then(function() {\n              // The user is authenticated, continue to the requested route\n              if (sp.authorize) {\n                if (authorizeStateConfig(sp)) {\n                  goToRoute(toRoute);\n                } else {\n                  stateChangeUnauthorizedEvent(toRoute);\n                }\n              } else {\n                goToRoute(toRoute);\n              }\n            }, function() {\n              // The user is not authenticated, emit the necessary event\n              routeChangeUnauthenticatedEvent(toRoute);\n            });\n          } else if (sp.waitForUser && $user.currentUser === null) {\n            event.preventDefault();\n\n            $user.get().finally(function() {\n              goToRoute(toRoute);\n            });\n          } else if ($user.currentUser && sp.authorize) {\n            if (!authorizeStateConfig(sp)) {\n              event.preventDefault();\n              routeChangeUnauthorizedEvent(toRoute);\n            }\n          } else if (toRoute.$$route.originalPath === config.loginRoute) {\n            /*\n              If the user is already logged in, we will redirect\n              away from the login page and send the user to the\n              post login route.\n             */\n            if ($user.currentUser && $user.currentUser.href) {\n              event.preventDefault();\n              goToRoute(config.defaultPostLoginRoute);\n            }\n          }\n        });\n      };\n\n      function authorizeRouteConfig(spRouteConfig) {\n        var sp = spRouteConfig;\n\n        if (sp && sp.authorize && sp.authorize.group) {\n          return $user.currentUser.inGroup(sp.authorize.group);\n        }\n\n        console.error('Unknown authorize configuration for spRouteConfig', sp);\n        return false;\n      }\n\n      /**\n       * @ngdoc function\n       *\n       * @name stormpath#uiRouter\n       *\n       * @methodOf stormpath.$stormpath\n       *\n       * @param {object} config\n       *\n       * * **`autoRedirect`** - Defaults to true.  After the user logs in at\n       * the state defined by `loginState`, they will be redirected back to the\n       * state that was originally requested.\n       *\n       * * **`defaultPostLoginState`**  - Where the user should be sent, after login,\n       * if they have visited the login page directly.  If you do not define a value,\n       * nothing will happen at the login state.  You can alternatively use the\n       * {@link stormpath.authService.$auth#events_$authenticated $authenticated} event to know\n       * that login is successful.\n       *\n       * * **`forbiddenState`** - The UI state name that we should send the user\n       * to if they try to an access a view that they are not authorized to view.\n       * This happens in response to an `authorize` rule in one of your\n       * {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configurations}\n       *\n       * * **`loginState`** - The UI state name that we should send the user\n       * to if they need to login.  You'll probably use `login` for this value.\n       *\n       * @description\n       *\n       * Call this method to enable the integration with the UI Router module.\n       *\n       * When enabled, you can define {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configurations} on your UI states.\n       * This object allows you to define access control for the state.\n       *\n       * You can pass config options to this integration, the options control the\n       * default behavior around \"need to login\" and \"forbidden\" situations.\n       * If you wish to implement your own logic for these situations, simply\n       * omit the options and use the events (documented below) to know\n       * what is happening in the application.\n       *\n       * @example\n       *\n       * <pre>\n       * angular.module('myApp')\n       *   .run(function($stormpath){\n       *     $stormpath.uiRouter({\n       *       forbiddenState: 'forbidden',\n       *       defaultPostLoginState: 'main',\n       *       loginState: 'login'\n       *     });\n       *   });\n       * </pre>\n       */\n      StormpathService.prototype.uiRouter = function uiRouter(config){\n        var self = this;\n        config = typeof config === 'object' ? config : {};\n        this.stateChangeInterceptor(config);\n\n        if(config.loginState){\n          self.unauthenticatedWather = $rootScope.$on(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHENTICATED,function(e,toState,toParams){\n            self.postLogin = {\n              toState: toState,\n              toParams: toParams\n            };\n            $state.go(config.loginState);\n          });\n        }\n\n        $rootScope.$on(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME,function(){\n          if(self.postLogin && (config.autoRedirect !== false)){\n            $state.go(self.postLogin.toState,self.postLogin.toParams).then(function(){\n              self.postLogin = null;\n            });\n          }else if(config.defaultPostLoginState){\n            $state.go(config.defaultPostLoginState);\n          }\n        });\n\n        if(config.forbiddenState){\n          self.forbiddenWatcher = $rootScope.$on(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHORIZED,function(){\n            $state.go(config.forbiddenState);\n          });\n        }\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name stormpath#ngRouter\n       *\n       * @methodOf stormpath.$stormpath\n       *\n       * @param {object} config\n       *\n       * * **`autoRedirect`** - Defaults to true.  After the user logs in at\n       * the route defined by `loginRoute`, they will be redirected back to the\n       * route that was originally requested.\n       *\n       * * **`defaultPostLoginRoute`**  - Where the user should be sent, after login,\n       * if they have visited the login page directly.  If you do not define a value,\n       * nothing will happen at the login route.  You can alternatively use the\n       * {@link stormpath.authService.$auth#events_$authenticated $authenticated} event to know\n       * that login is successful.\n       *\n       * * **`forbiddenRoute`** - The route that we should send the user\n       * to if they try to an access a view that they are not authorized to view.\n       * This happens in response to an `authorize` rule in one of your\n       * {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configurations}\n       *\n       * * **`loginRoute`** - The route name that we should send the user\n       * to if they need to login.  You'll probably use `login` for this value.\n       *\n       * @description\n       *\n       * Call this method to enable the integration with the ngRoute module.\n       *\n       * When enabled, you can define {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configurations} on your routes.\n       * This object allows you to define access control for the route.\n       *\n       * You can pass config options to this integration, the options control the\n       * default behavior around \"need to login\" and \"forbidden\" situations.\n       * If you wish to implement your own logic for these situations, simply\n       * omit the options and use the events (documented below) to know\n       * what is happening in the application.\n       *\n       * @example\n       *\n       * <pre>\n       * angular.module('myApp')\n       *   .run(function($stormpath){\n       *     $stormpath.ngRouter({\n       *       forbiddenRoute: '/forbidden',\n       *       defaultPostLoginRoute: '/home',\n       *       loginRoute: '/login'\n       *     });\n       *   });\n       * </pre>\n       */\n      StormpathService.prototype.ngRouter = function ngRouter(config) {\n        var self = this;\n\n        config = typeof config === 'object' ? config : {};\n\n        this.routeChangeInterceptor(config);\n\n        if (config.loginRoute) {\n          this.unauthenticatedWather = $rootScope.$on(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHENTICATED, function(event, toRoute) {\n            self.postLogin = {\n              toRoute: toRoute\n            };\n\n            $location.path(config.loginRoute);\n          });\n        }\n\n        $rootScope.$on(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME, function() {\n          if (self.postLogin && config.autoRedirect !== false) {\n            $location.path(self.postLogin.toRoute);\n            self.postLogin = null;\n          } else if (config.defaultPostLoginRoute) {\n            $location.path(config.defaultPostLoginRoute);\n          }\n        });\n\n        if (config.forbiddenRoute) {\n          this.forbiddenWatcher = $rootScope.$on(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHORIZED, function() {\n            $location.path(config.forbiddenRoute);\n          });\n        }\n      };\n\n      StormpathService.prototype.regexAttrParser = function regexAttrParser(value){\n        var expr;\n        if(value instanceof RegExp){\n          expr = value;\n        }else if(value && /^\\/.+\\/[gim]?$/.test(value)){\n          expr = new RegExp(value.split('/')[1],value.split('/')[2]);\n        }else{\n          expr = value;\n        }\n        return expr;\n      };\n\n      function UrlEncodedFormParser(){\n\n        // Copy & modify from https://github.com/hapijs/qs/blob/master/lib/stringify.js\n\n        this.delimiter = '&';\n        this.arrayPrefixGenerators = {\n          brackets: function (prefix) {\n            return prefix + '[]';\n          },\n          indices: function (prefix, key) {\n            return prefix + '[' + key + ']';\n          },\n          repeat: function (prefix) {\n            return prefix;\n          }\n        };\n        return this;\n      }\n      UrlEncodedFormParser.prototype.stringify = function stringify(obj, prefix, generateArrayPrefix) {\n\n        if (obj instanceof Date) {\n          obj = obj.toISOString();\n        }\n        else if (obj === null) {\n          obj = '';\n        }\n\n        if (typeof obj === 'string' ||\n          typeof obj === 'number' ||\n          typeof obj === 'boolean') {\n\n          return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];\n        }\n\n        var values = [];\n\n        if (typeof obj === 'undefined') {\n          return values;\n        }\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          if (Array.isArray(obj)) {\n            values = values.concat(this.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));\n          }\n          else {\n            values = values.concat(this.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));\n          }\n        }\n\n        return values;\n      };\n      UrlEncodedFormParser.prototype.encode = function encode(obj, options) {\n\n        options = options || {};\n        var delimiter = typeof options.delimiter === 'undefined' ? this.delimiter : options.delimiter;\n\n        var keys = [];\n\n        if (typeof obj !== 'object' ||\n          obj === null) {\n\n          return '';\n        }\n\n        var arrayFormat;\n        if (options.arrayFormat in this.arrayPrefixGenerators) {\n          arrayFormat = options.arrayFormat;\n        }\n        else if ('indices' in options) {\n          arrayFormat = options.indices ? 'indices' : 'repeat';\n        }\n        else {\n          arrayFormat = 'indices';\n        }\n\n        var generateArrayPrefix = this.arrayPrefixGenerators[arrayFormat];\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          keys = keys.concat(this.stringify(obj[key], key, generateArrayPrefix));\n        }\n\n        return keys.join(delimiter);\n      };\n\n      return new StormpathService();\n    }\n  ];\n}])\n.run(['$rootScope','$user','STORMPATH_CONFIG',function($rootScope,$user,STORMPATH_CONFIG){\n  $rootScope.user = $user.currentUser || null;\n  $user.get().finally(function(){\n    $rootScope.user = $user.currentUser;\n  });\n  $rootScope.$on(STORMPATH_CONFIG.GET_USER_EVENT,function(){\n    $rootScope.user = $user.currentUser;\n  });\n  $rootScope.$on(STORMPATH_CONFIG.SESSION_END_EVENT,function(){\n    $rootScope.user = $user.currentUser;\n  });\n  $rootScope.$on(STORMPATH_CONFIG.SESSION_END_ERROR_EVENT,function(event, error){\n    console.error('Logout error', error);\n  });\n  $rootScope.$on(STORMPATH_CONFIG.UNAUTHENTICATED_EVENT,function(event, error){\n    console.error('UNAUTHENTICATED_EVENT');\n  });\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUser:ifUser\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is logged in.\n *\n * @example\n *\n * <pre>\n * <div class=\"container\">\n *   <h3 if-user>Hello, {{user.fullName}}</h3>\n * </div>\n * </pre>\n */\n.directive('ifUser',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(user){\n        if(user && user.href){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifNotUser:ifNotUser\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is NOT logged in.\n *\n * @example\n *\n * <pre>\n * <div class=\"container\">\n *   <h3 if-not-user>Hello, you need to login</h3>\n * </div>\n * </pre>\n */\n.directive('ifNotUser',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(user){\n        if(user && user.href){\n          element.addClass('ng-hide');\n        }else{\n          element.removeClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserInGroup:ifUserInGroup\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is logged in\n * and is a member of the group that is specified by the expression.\n *\n * The attribute value MUST be one of:\n *\n * * A string expression, surrounded by quotes\n * * A reference to a property on the $scope.  That property can be a string or\n * regular expression.\n *\n * **Note**: This feature depends on the data that is returned by the\n * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_CURRENT_USER_URI CURRENT_USER_URI}.\n * Your server should expand the account's groups before returning the user.\n * If you are using [express-stormpath](https://github.com/stormpath/express-stormpath), simply use\n * [Automatic Expansion](http://docs.stormpath.com/nodejs/express/latest/user_data.html#automatic-expansion)\n *\n * # Using Regular Expressions\n *\n * If using a string expression as the attribute value, you can pass a regular\n * expression by wrapping it in the literal\n * syntax, e.g.\n *  * `'/admins/'` would match any group which has *admins* in the name\n *  * `'/admin$/'` would match any group were the name **ends with** *admin*\n *\n * If referencing a scope property, you should create the value as a RegExp type,\n * e.g.:\n *\n *  <pre>\n *    $scope.matchGroup = new RegExp(/admins/);\n *  </pre>\n *\n * All regular expressions are evaluated via\n * [RegExp.prototype.test](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test)\n *\n * @example\n *\n * <pre>\n *   <script type=\"text/javascript\">\n *     function SomeController($scope){\n *       $scope.matchGroup = /admins/;\n *     }\n *   <script>\n *   <div ng-controller=\"SomeController\">\n *     <h3 if-user-in-group=\"'admins'\">\n *       Hello, {{user.fullName}}, you are an administrator\n *     </h3>\n *\n *     <div if-user-in-group=\"'/admins/'\">\n *        <!-- would match any group which has *admins* in the name -->\n *     </div>\n *     <div if-user-in-group=\"matchGroup\">\n *        <!-- equivalent to the last example -->\n *     </div>\n *     <div if-user-in-group=\"'/admin$/'\">\n *        <!-- would match any group were the name **ends with** *admin* -->\n *     </div>\n *   </div>\n * </pre>\n */\n.directive('ifUserInGroup',['$user','$rootScope','$parse','$stormpath',function($user,$rootScope,$parse,$stormpath){\n\n  return {\n    link: function(scope,element,attrs){\n\n      var expr;\n      var attrExpr = attrs.ifUserInGroup;\n\n      function evalElement(){\n        var user = $user.currentUser;\n        if(user && user.groupTest(expr || attrExpr)){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      }\n\n      if(attrExpr){\n        scope.$watch($parse(attrExpr),function(value){\n          expr = $stormpath.regexAttrParser(value);\n          evalElement();\n        });\n        $rootScope.$watch('user',function(){\n          evalElement();\n        });\n      }\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserNotInGroup:ifUserNotInGroup\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is logged in\n * and is NOT a member of the group that is specified by the expression.\n *\n * This is the inverse of {@link stormpath.ifUserInGroup:ifUserInGroup ifUserInGroup},\n * please refer to that directive for full usage information.\n *\n * **Note**: This feature depends on the data that is returned by the\n * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_CURRENT_USER_URI CURRENT_USER_URI}.\n * Your server should expand the account's groups before returning the user.\n * If you are using [express-stormpath](https://github.com/stormpath/express-stormpath), simply use\n * [Automatic Expansion](http://docs.stormpath.com/nodejs/express/latest/user_data.html#automatic-expansion)\n *\n * @example\n *\n * <pre>\n *   <div class=\"container\">\n *     <h3 if-user-not-in-group=\"'admins'\">\n *       Hello, {{user.fullName}}, please request administrator access\n *     </h3>\n *   </div>\n * </pre>\n */\n.directive('ifUserNotInGroup',['$user','$rootScope','$parse','$stormpath',function($user,$rootScope,$parse,$stormpath){\n  return {\n    link: function(scope,element,attrs){\n\n      var expr;\n      var attrExpr = attrs.ifUserNotInGroup;\n\n      function evalElement(){\n        var user = $user.currentUser;\n        if(user && user.groupTest(expr || attrExpr)){\n          element.addClass('ng-hide');\n        }else{\n          element.removeClass('ng-hide');\n        }\n      }\n\n      if(attrExpr){\n        scope.$watch($parse(attrExpr),function(value){\n          expr = $stormpath.regexAttrParser(value);\n          evalElement();\n        });\n        $rootScope.$watch('user',function(){\n          evalElement();\n        });\n      }\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.whileResolvingUser:while-resolving-user\n *\n * @description\n *\n * # [DEPRECATED]\n * Please use {@link stormpath.ifUserStateUnknown:ifUserStateUnknown ifUserStateUnknown} instead.\n *\n */\n.directive('whileResolvingUser',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(){\n        if($user.currentUser || ($user.currentUser===false)){\n          element.addClass('ng-hide');\n        }else{\n          element.removeClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserStateKnown:ifUserStateKnown\n *\n * @description\n *\n * Use this directive to show an element once the user state is known.\n * The inverse of {@link stormpath.ifUserStateUnknown:ifUserStateUnknown ifUserStateUnknown}. You can\n * use this directive to show an element after we know if the user is logged in\n * or not.\n *\n * @example\n *\n * <pre>\n * <div if-user-state-known>\n *   <li if-not-user>\n *      <a ui-sref=\"login\">Login</a>\n *    </li>\n *    <li if-user>\n *        <a ui-sref=\"main\" sp-logout>Logout</a>\n *    </li>\n * </div>\n * </pre>\n */\n.directive('ifUserStateKnown',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(){\n        if($user.currentUser || ($user.currentUser===false)){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserStateUnknown:ifUserStateUnknown\n *\n * @description\n *\n * Use this directive to show an element while waiting to know if the user\n * is logged in or not.  This is useful if you want to show a loading graphic\n * over your application while you are waiting for the user state.\n *\n * @example\n *\n * <pre>\n * <div if-user-state-unknown>\n *   <p>Loading.. </p>\n * </div>\n * </pre>\n */\n.directive('ifUserStateUnknown',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(){\n        if($user.currentUser === null){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spLogout:spLogout\n *\n * @description\n *\n * This directive adds a click handler to the element.  When clicked, the user will be logged out.\n *\n * **Note**: the click action triggers the logout request to the server and\n * deletes your authentication information, it does not automatically redirect\n * you to any view (we leave this in your control).\n *\n * The common use-case is to redirect users to the login view after they\n * logout.  This can be done by observing the\n * {@link stormpath.authService.$auth#events_$sessionEnd $sessionEnd} event.\n * For example, if you are using UI Router:\n *\n * ```javascript\n * $rootScope.$on('$sessionEnd',function () {\n *   $state.transitionTo('login');\n * });\n * ```\n *\n * @example\n *\n * <pre>\n *   <a ui-sref=\"main\" sp-logout>Logout</a>\n * </pre>\n */\n.directive('spLogout',['$auth',function($auth){\n  return{\n    link: function(scope,element){\n      element.on('click',function(){\n        $auth.endSession();\n      });\n    }\n  };\n}]);\n\n'use strict';\n/**\n * @ngdoc overview\n *\n * @name  stormpath.authService\n *\n * @description\n *\n * This module provides the {@link stormpath.authService.$auth $auth} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\n/**\n * @ngdoc object\n *\n * @name stormpath.authService.$authProvider\n *\n * @description\n *\n * Provides the {@link stormpath.authService.$auth $auth} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\nangular.module('stormpath.auth',['stormpath.CONFIG', 'stormpath.oauth', 'stormpath.utils'])\n.config(['$injector','STORMPATH_CONFIG',function $authProvider($injector,STORMPATH_CONFIG){\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.authService.$auth\n   *\n   * @description\n   *\n   * The auth service provides methods for authenticating a user, aka\n   * \"logging in\" the user.\n   */\n  var authServiceProvider = {\n    $get: ['$http','$user','$rootScope','$spFormEncoder','$q','$spErrorTransformer', '$isCurrentDomain', 'StormpathOAuth', function authServiceFactory($http,$user,$rootScope,$spFormEncoder,$q, $spErrorTransformer, $isCurrentDomain, StormpathOAuth){\n\n      function AuthService(){\n        return this;\n      }\n      AuthService.prototype.authenticate = function authenticate(data) {\n        /**\n         * @ngdoc function\n         *\n         * @name  stormpath.authService.$auth#authenticate\n         *\n         * @methodOf stormpath.authService.$auth\n         *\n         * @param {Object} credentialData\n         *\n         * An object literal for passing username & password, or social provider\n         * token.\n         *\n         * @returns {promise}\n         *\n         * A promise that is resolved with the authentication response or error\n         * response (both are response objects from the $http service).\n         *\n         * @description\n         *\n         * Logs the user in.\n         *\n         * Sends the provided credential data to your backend server. The server\n         * handler should verify the credentials and return an access token,\n         * which is stored in an HTTP-only cookie.\n         *\n         * @example\n         *\n         * ## Username & Password example\n         *\n         * <pre>\n         * myApp.controller('LoginCtrl', function ($scope, $auth, $state) {\n         *   $scope.errorMessage = null;\n         *   $scope.formData = {\n         *     username: '',         // Expose to user as email/username field\n         *     password: '',\n         *   };\n         *\n         *   // Use this method with ng-submit on your form\n         *   $scope.login = function login(formData){\n         *     $auth.authenticate(formData)\n         *      .then(function(){\n         *        console.log('login success');\n         *        $state.go('home');\n         *      })\n         *      .catch(function(err){\n         *        $scope.errorMessage = err.message;\n         *      });\n         *   }\n         *\n         * });\n         * </pre>\n         *\n         * ## Social Login example\n         *\n         * <pre>\n         * myApp.controller('LoginCtrl', function ($scope, $auth, $state) {\n         *   $scope.errorMessage = null;\n         *   $scope.formData = {\n         *     providerId: 'facebook',         // Get access token from FB sdk login\n         *     accessToken: 'CABTmZxAZBxBADbr1l7ZCwHpjivBt9T0GZBqjQdTmgyO0OkUq37HYaBi4F23f49f5',\n         *   };\n         *\n         *   // Use this method with ng-submit on your form\n         *   $scope.login = function login(formData){\n         *     $auth.authenticate(formData)\n         *      .then(function(){\n         *        console.log('login success');\n         *        $state.go('home');\n         *      })\n         *      .catch(function(err){\n         *        $scope.errorMessage = err.message;\n         *      });\n         *   }\n         *\n         * });\n         * </pre>\n         */\n\n\n        function success(httpResponse){\n          $user.get(true).then(function(){\n            authenticatedEvent(httpResponse);\n          });\n        }\n\n        function error(httpResponse){\n          authenticationFailureEvent(httpResponse);\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        }\n\n        var headers = {\n          Accept: 'application/json'\n        };\n\n        var authEndpoint = STORMPATH_CONFIG.getUrl('AUTHENTICATION_ENDPOINT');\n        var op;\n\n        if ($isCurrentDomain(authEndpoint)) {\n          op = $http($spFormEncoder.formPost({\n            url: authEndpoint,\n            method: 'POST',\n            headers: headers,\n            withCredentials: true,\n            data: data\n          }));\n        } else {\n          var remoteData = angular.extend({}, data);\n\n          // Handles different naming expected in local and client API login\n          if (remoteData.login) {\n            remoteData.username = remoteData.login;\n            delete remoteData.login;\n          }\n\n          op = StormpathOAuth.authenticate(remoteData, headers);\n        }\n\n        return op.then(success, error);\n      };\n\n      /**\n       * @ngdoc event\n       *\n       * @name stormpath.authService.$user#$sessionEnd\n       *\n       * @eventOf stormpath.authService.$auth\n       *\n       * @eventType broadcast on root scope\n       *\n       * @param {Object} event\n       *\n       * Angular event object.\n\n       * @description\n       *\n       * This event is broadcast when a call to\n       * {@link stormpath.authService.$auth#methods_endSession $auth.endSession()}\n       * is successful.  Use this event when you want to do something after the\n       * user has logged out.\n       */\n      function endSessionEvent () {\n        $rootScope.$broadcast(STORMPATH_CONFIG.SESSION_END_EVENT);\n      }\n\n      /**\n       * @ngdoc function\n       *\n       * @name stormpath.authService.$auth#endSession\n       *\n       * @methodOf stormpath.authService.$auth\n       *\n       * @return {promise} A promise that is resolved when the logout request\n       * of the server is complete.\n       *\n       * @description Use this method to log the user out. It triggers a request\n       * to the `/logout` endpoint on the server.  This will delete the cookies\n       * that are used for authentication.  The\n       * {@link stormpath.authService.$auth#events_$sessionEnd $sessionEnd}\n       * event will be emitted after a successful logout.\n       */\n      AuthService.prototype.endSession = function endSession(){\n        var destroyEndpoint = STORMPATH_CONFIG.getUrl('DESTROY_SESSION_ENDPOINT');\n        var op;\n\n        if ($isCurrentDomain(destroyEndpoint)) {\n          op = $http.post(destroyEndpoint, null, {\n            headers: {\n              'Accept': 'application/json',\n              'Content-Type': 'application/x-www-form-urlencoded'\n            }\n          });\n        } else {\n          op = StormpathOAuth.revoke();\n        }\n\n        op.finally(function(){\n          endSessionEvent();\n        }).catch(function(httpResponse){\n          $rootScope.$broadcast(STORMPATH_CONFIG.SESSION_END_ERROR_EVENT, httpResponse);\n        });\n\n        return op;\n      };\n\n      function authenticatedEvent(response){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.authService.$auth#$authenticated\n         *\n         * @eventOf stormpath.authService.$auth\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {httpResponse} httpResponse\n         *\n         * The http response from the $http service.  If you are writing your access tokens to the response body\n         * when a user authenticates, you will want to use this response object to get access to that token.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.authService.$auth#methods_authenticate $auth.authenticate()}\n         * is successful.\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME,response);\n      }\n      function authenticationFailureEvent(response){\n        $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_FAILURE_EVENT_NAME,response);\n      }\n      return new AuthService();\n    }]\n  };\n\n  $injector.get('$provide')\n    .provider(STORMPATH_CONFIG.AUTH_SERVICE_NAME,authServiceProvider);\n\n}]);\n\n'use strict';\n\n/**\n* @ngdoc object\n*\n* @name stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n*\n* @description\n*\n* This constant allows you to configure the internal settings of the module,\n* such as authentication endpoints and the names of events. These properties\n* must be modified within a config block.\n*\n* **Example:**\n* <pre>\n*     angular.module('myapp')\n*       .config(function(STORMPATH_CONFIG){\n*           STORMPATH_CONFIG.ENDPOINT_PREFIX = 'http://api.mydomain.com';\n*       });\n* </pre>\n*/\n\nangular.module('stormpath.CONFIG',[])\n.constant('STORMPATH_CONFIG',(function stormpathConfigBuilder(){\n  var c={\n    /**\n    * @ngdoc property\n    *\n    * @name AUTHENTICATION_SUCCESS_EVENT_NAME\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$authenticated`\n    *\n    * The name of the event that is fired when a user logs in, after\n    * successfully submitting the login form.\n    *\n    */\n    AUTHENTICATION_SUCCESS_EVENT_NAME: '$authenticated',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name AUTHENTICATION_FAILURE_EVENT_NAME\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$authenticationFailure`\n    *\n    * The name of the event that is fired when the user posts\n    * invalid login credentials to the login form.\n    */\n    AUTHENTICATION_FAILURE_EVENT_NAME: '$authenticationFailure',\n\n\n    /**\n     * @ngdoc property\n     *\n     * @name AUTH_SERVICE_NAME\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Default: `$auth`\n     *\n     * The name of the authentication service, this changes the\n     * service name that you inject.\n    */\n    AUTH_SERVICE_NAME: '$auth',\n\n    /**\n     * @ngdoc property\n     *\n     * @name AUTO_AUTHORIZED_URIS\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Default: `['/me$']`\n     *\n     * The list of URLs to match when making requests.  If an OAuth strategy is\n     * being used and the request matches this URL, this library will automatically\n     * add the `Authorization: Bearer <token>` header to the request.\n    */\n    AUTO_AUTHORIZED_URIS: ['/me$'],\n\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_SERVICE_NAME\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Default: `$socialLogin`\n     *\n     * The name of the social login service, this changes the\n     * service name that you inject.\n    */\n    SOCIAL_LOGIN_SERVICE_NAME: '$socialLogin',\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_RESPONSE_TYPE\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * The response type requested from the Stormpath Social Login v2 API.\n     * Determines the type of token that will be returned for OAuth authentication\n     * against the Stormpath OAuth API, when making social login attempts.\n    */\n    SOCIAL_LOGIN_RESPONSE_TYPE: 'stormpath_token',\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_OPTIONS\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Options that are set for a given social authentication provider when\n     * making a social authentication request. These are appended to the request\n     * as query parameters, and will override any default options, or options\n     * set in the Stormpath admin console.\n     *\n     * The settings are mapped by providerId of a directory (e.g. `google`, `facebook`).\n     *\n     * Additional providers may be added to the object, but must all be in lowercase.\n    */\n    SOCIAL_LOGIN_OPTIONS: {\n      google: {},\n      facebook: {},\n      twitter: {},\n      linkedin: {}\n    },\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_REDIRECT_URI\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * The URI that the social login flow will redirect to after a login attempt.\n     * This URI is relative to the base application URI.\n    */\n    SOCIAL_LOGIN_REDIRECT_URI: '',\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_AUTHORIZE_URI\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * The relative URI of the endpoint used for social auth.\n     * Should <b>not</b> be changed if Client API is used.\n    */\n    SOCIAL_LOGIN_AUTHORIZE_ENDPOINT: '/authorize',\n\n    /**\n    * @ngdoc property\n    *\n    * @name AUTHENTICATION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/login`\n    *\n    * The URI that the login form will post to.  The endpoint MUST accept data\n    * in the following format:\n    *\n    * ```\n    * {\n    *     username: '',\n    *     password: ''\n    * }\n    * ```\n    */\n    AUTHENTICATION_ENDPOINT: '/login',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name CURRENT_USER_URI\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/me`\n    *\n    * The URI that is used to fetch the account object of\n    * the currently logged in user.  This endpoint MUST:\n    *  * Respond with a JSON object that is the Stormpath account object,\n    *  if the user has an active session.\n    *  * Respond with `401 Unauthorized` if the user has no session.\n    */\n    CURRENT_USER_URI: '/me',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name DESTROY_SESSION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/logout`\n    *\n    * The URL that the {@link stormpath.spLogout:spLogout spLogout} directive\n    * will make a GET request to, this endpoint MUST delete the access token\n    * cookie, XSRF token cookie, and any other cookies that relate to the user\n    * session.\n    */\n    DESTROY_SESSION_ENDPOINT: '/logout',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name EMAIL_VERIFICATION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/verify`\n    *\n    * The endpoint that is used for verifying an account that requires email\n    * verification.  Used by\n    * {@link stormpath.userService.$user#methods_verify $user.verify()} to POST\n    * the `sptoken` that was delivered to the user by email.\n    *\n    * This endpoint MUST accept a POST request with the following format and\n    * use Stormpath to verify the token:\n    * ```\n    * {\n    *   sptoken: '<token from email sent to user>'\n    * }\n    * ```\n    *\n    */\n    EMAIL_VERIFICATION_ENDPOINT: '/verify',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name ENDPOINT_PREFIX\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: *none*\n    *\n    * A prefix, e.g. \"base URL\" to add to all endpoints that are used by this SDK.\n    * Use this if your backend API is running on a different port or domain than\n    * your Angular application.  Omit the trailing forward slash.\n    *\n    * **NOTE:** This may trigger\n    * [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)\n    * behaviour in the browser, and your server\n    * will need to respond to requests accordingly.  If you are using our\n    * Express SDK see\n    * [allowedOrigins](https://github.com/stormpath/stormpath-sdk-express#allowedOrigins)\n    *\n    * **Example:**\n    * <pre>\n    *   ENDPOINT_PREFIX = 'http://api.mydomain.com'\n    * </pre>\n    */\n    ENDPOINT_PREFIX: '',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name GET_USER_EVENT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$currentUser`\n    *\n    * The name of the event that is fired when\n    * {@link stormpath.userService.$user#methods_get $user.get()}\n    * is resolved with a user object.\n    */\n    GET_USER_EVENT: '$currentUser',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name NOT_LOGGED_IN_EVENT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$notLoggedin`\n    *\n    * The name of the event that is fired when\n    * {@link stormpath.userService.$user#methods_get $user.get()}\n    * is rejected without a user.\n    */\n    NOT_LOGGED_IN_EVENT: '$notLoggedin',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name FORGOT_PASSWORD_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/forgot`\n    *\n    * The endpoint that is used by\n    * {@link stormpath.userService.$user#methods_passwordResetRequest $user.passwordResetRequest()}\n    * to create password reset tokens.\n    */\n    FORGOT_PASSWORD_ENDPOINT: '/forgot',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name CHANGE_PASSWORD_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/change`\n    *\n    * The endpoint that is used by\n    * {@link stormpath.userService.$user#methods_verifyPasswordResetToken $user.verifyPasswordResetToken()} and\n    * {@link stormpath.userService.$user#methods_resetPassword $user.resetPassword()}\n    * to verify and consume password reset tokens (change a user's password with the token).\n    */\n    CHANGE_PASSWORD_ENDPOINT: '/change',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name SESSION_END_EVENT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$sessionEnd`\n    *\n    * The name of the event that is fired when the user logs out via the\n    * {@link stormpath.spLogout:spLogout spLogout}\n    * directive\n    */\n    SESSION_END_EVENT: '$sessionEnd',\n\n    SESSION_END_ERROR_EVENT: '$sessionEndError',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name STATE_CHANGE_UNAUTHENTICATED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$stateChangeUnauthenticated`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * UI Router state that requires authentication, but the user is not\n    * authenticated.\n    */\n    STATE_CHANGE_UNAUTHENTICATED: '$stateChangeUnauthenticated',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name STATE_CHANGE_UNAUTHORIZED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$stateChangeUnauthorized`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * UI Router state that has an access control rule which the user does not\n    * meet (such as not being in a specified group)\n    */\n    STATE_CHANGE_UNAUTHORIZED: '$stateChangeUnauthorized',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name ROUTE_CHANGE_UNAUTHENTICATED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$routeChangeUnauthenticated`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * route that requires authentication, but the user is not\n    * authenticated.\n    */\n    ROUTE_CHANGE_UNAUTHENTICATED: '$routeChangeUnauthenticated',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name ROUTE_CHANGE_UNAUTHORIZED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$routeChangeUnauthorized`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * route that has an access control rule which the user does not\n    * meet (such as not being in a specified group)\n    */\n    ROUTE_CHANGE_UNAUTHORIZED: '$routeChangeUnauthorized',\n\n    /**\n    * @ngdoc property\n    *\n    * @name OAUTH_REQUEST_ERROR\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$oAuthRequestError`\n    *\n    * The name of the event that is fired when the user attempts OAuth-based\n    * authentication, and fails due to an OAuth issue.\n    */\n    OAUTH_REQUEST_ERROR: '$oAuthRequestError',\n\n    /**\n    * @ngdoc property\n    *\n    * @name OAUTH_AUTHENTICATION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/oauth/token`\n    *\n    * The endpoint that is used to authenticate and refresh using OAuth tokens.\n    * This endpoint MUST support password and refresh_token grant authentication\n    * flows.\n    */\n    OAUTH_AUTHENTICATION_ENDPOINT: '/oauth/token',\n\n    /**\n    * @ngdoc property\n    * @name OAUTH_REVOKE_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/oauth/revoke`\n    *\n    * The endpoint that is used to revoke OAuth tokens.\n    */\n    OAUTH_REVOKE_ENDPOINT: '/oauth/revoke',\n\n    /**\n    * @ngdoc property\n    * @name OAUTH_REVOKE_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * The name under which tokens are stored in the token storage mechanism.\n    * Might not be relevant if the underlying storage mechanism is not key-value\n    * based.\n    *\n    * See {@link stormpath.tokenStore.TokenStoreManager TokenStoreManager} for more detail.\n    */\n    OAUTH_TOKEN_STORAGE_NAME: 'stormpath:token',\n\n    /**\n    * @ngdoc property\n    *\n    * @name REGISTER_URI\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/register`\n    *\n    * The endpoint that is used by\n    * {@link stormpath.userService.$user#methods_create $user.create()}\n    * to POST new users.  This endpoint MUST accept a stormpath account object\n    * and use Stormpath to create the new user.\n    */\n    REGISTER_URI: '/register',\n\n    /**\n    * @ngdoc property\n    *\n    * @name REGISTERED_EVENT_NAME\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$registered`\n    *\n    * The name of the event that is fired when\n    * {@link stormpath.userService.$user#methods_create $user.create()}\n    * is resolved with an account that was successfully created\n    */\n    REGISTERED_EVENT_NAME: '$registered',\n\n    /**\n    * @ngdoc property\n    *\n    * @name OAUTH_DEFAULT_TOKEN_STORE_TYPE\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `localStorage`\n    *\n    * The default type of local storage used by\n    * {@link stormpath.oauth.StormpathOAuthTokenProvider}.\n    */\n    OAUTH_DEFAULT_TOKEN_STORE_TYPE: 'localStorage'\n\n  };\n\n  c.getUrl = function(key) {\n    return this.ENDPOINT_PREFIX + this[key];\n  };\n\n  c.getSocialLoginConfiguration = function(key) {\n    var canonicalKey = key ? key.toLowerCase() : '';\n    return this.SOCIAL_LOGIN_OPTIONS[canonicalKey] || {};\n  };\n  return c;\n})());\n\n'use strict';\n\nangular.module('stormpath')\n\n.controller('SpEmailVerificationCtrl', ['$scope','$location','$user',function ($scope,$location,$user) {\n  $scope.showVerificationError = false;\n  $scope.verifying = false;\n  $scope.reVerificationSent = false;\n  $scope.needsReVerification = false;\n  $scope.resendFailed = false;\n  $scope.formModel = {\n    username: ''\n  };\n  if($location.search().sptoken){\n    $scope.verifying = true;\n    $user.verify($location.search().sptoken)\n      .then(function(){\n        $scope.verified = true;\n      })\n      .catch(function(){\n        $scope.needsReVerification = true;\n        $scope.showVerificationError = true;\n      })\n      .finally(function(){\n        $scope.verifying = false;\n      });\n  }else{\n    $scope.needsReVerification = true;\n    $scope.showVerificationError = true;\n  }\n  $scope.submit = function(){\n    $scope.posting = true;\n    $scope.resendFailed = false;\n    $scope.showVerificationError = false;\n    $user.resendVerificationEmail({login: $scope.formModel.username})\n      .then(function(){\n        $scope.reVerificationSent = true;\n      })\n      .catch(function(){\n        $scope.resendFailed = true;\n      }).finally(function(){\n        $scope.posting = false;\n      });\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spEmailVerification:spEmailVerification\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n * @description\n *\n * Use this directive on the page that users land on when they click an email verification link.\n * These links are sent after a user registers, see\n * {@link stormpath.spRegistrationForm:spRegistrationForm spRegistrationForm}.\n *\n * This directive will render a view that does the following:\n * * Verifies that the current URL has an `sptoken` in it.  Shows an error if not.\n * * Verifies the given `sptoken` with Stormpath, then:\n *   * If the token is valid, tell the user that the confirmation is complete and prompt the user to login.\n *   * If the token is invalid (it is expired or malformed), we prompt the user to enter\n *     their email address, so that we can try sending them a new link.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-email-verification></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-email-verification template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spEmailVerification',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spEmailVerification.tpl.html';\n    },\n    controller: 'SpEmailVerificationCtrl'\n  };\n});\n\n'use strict';\n\nangular.module('stormpath')\n\n.controller('SpLoginFormCtrl', ['$scope','$auth','$viewModel',function ($scope,$auth,$viewModel) {\n  $scope.viewModel = null;\n\n  $viewModel.getLoginModel().then(function (model) {\n\n    model.accountStores = model.accountStores.filter(function (accountStore) {\n      return accountStore.authorizeUri && accountStore.authorizeUri !== null;\n    });\n\n    $scope.viewModel = model;\n  }).catch(function (err) {\n    throw new Error('Could not load login view model from back-end: ' + err.message);\n  });\n\n  $scope.formModel = {};\n  $scope.posting = false;\n  $scope.submit = function(){\n    $scope.posting = true;\n    $scope.error = null;\n    $auth.authenticate($scope.formModel)\n      .catch(function(err){\n        $scope.posting = false;\n        $scope.error = err.message;\n      });\n  };\n}])\n\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spLoginForm:spLoginForm\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n * @description\n *\n * This directive will render a pre-built login form with all\n * the necessary fields.  After the login is a success, the following\n * will happen:\n *\n * * The {@link stormpath.authService.$auth#events_$authenticated $authenticated} event will\n * be fired.\n * *  If you have configured the {@link stormpath.$stormpath#methods_uiRouter UI Router Integration},\n * the following can happen:\n *  * The user is sent back to the view they originally requested.\n *  * The user is sent to a default view of your choice.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-login-form></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-login-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spLoginForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spLoginForm.tpl.html';\n    },\n    controller: 'SpLoginFormCtrl'\n  };\n});\n\n'use strict';\n\n/**\n* @ngdoc overview\n*\n* @name stormpath.oauth\n*\n* @description\n*\n* This module provides the {@link stormpath.oauth.StormpathOAuth StormpathOAuth}\n* and {@link stormpath.oauth.StormpathOAuthToken StormpathOAuthToken} services,\n* implementing a client-side OAuth2 workflow.\n*/\nangular.module('stormpath.oauth', ['stormpath.CONFIG', 'stormpath.utils', 'storpath.tokenStore'])\n\n/**\n* @ngdoc service\n*\n* @name stormpath.oauth.StormpathOAuthTokenProvider\n* @requires stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n* @description\n*\n* Provides the {@link stormpath.oauth.StormpathOAuthToken StormpathOAuthToken}\n* service.\n*/\n.provider('StormpathOAuthToken', ['STORMPATH_CONFIG',\nfunction StormpathOAuthTokenProvider(STORMPATH_CONFIG) {\n  var self = this;\n\n  this._tokenStoreType = STORMPATH_CONFIG.OAUTH_DEFAULT_TOKEN_STORE_TYPE;\n\n  /**\n  * @ngdoc method\n  * @name stormpath.oauth.StormpathOAuthTokenProvider#setTokenStoreType\n  * @methodOf stormpath.oauth.StormpathOAuthTokenProvider\n  *\n  * @param {String} tokenStoreType The name of the token store type the tokens should use to record and read their data.\n  *\n  * @description\n  *\n  * Sets the name of the token store type that the tokens use to store and load its data.\n  * See {@link stormpath.tokenStore.TokenStoreManager#getTokenStore TokenStoreManager.getTokenStore}\n  * for details.\n  */\n  this.setTokenStoreType = function setTokenStoreType(tokenStoreType) {\n    this._tokenStoreType = tokenStoreType;\n  };\n\n  /**\n  * @ngdoc service\n  * @name stormpath.oauth.StormpathOAuthToken\n  * @requires $q\n  * @requires stormpath.tokenStore.TokenStoreManager\n  *\n  * @description\n  *\n  * A service for managing OAuth tokens. It offers a simple interface for storing\n  * and reading tokens into a generic storage (backed by\n  * {@link stormpath.tokenStore.TokenStoreManager TokenStoreManager}), as well\n  * as utility methods for getting specific components of the token - the access\n  * token, refresh token, token type, as well as the Authorization header\n  * constructed from the token.\n  *\n  * It uses the token store type set in the provider, unless overrided via\n  * {@link stormpath.oauth.StormpathOAuthToken#setTokenStoreType StormpathOAuthToken.setTokenStoreType}.\n  */\n  this.$get = function $get($q, $normalizeObjectKeys, TokenStoreManager, $injector) {\n    function StormpathOAuthToken() {\n      this.tokenStore = TokenStoreManager.getTokenStore(self._tokenStoreType);\n    }\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#setTokenStoreType\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    * @param {String} tokenStoreType The name of the token store type this token should use to record and read their data.\n    *\n    * @description\n    *\n    * Sets the name of the token store type that this token uses to store and load its data.\n    * See {@link stormpath.tokenStore.TokenStoreManager#getTokenStore TokenStoreManager.getTokenStore}\n    * for details.\n    */\n    StormpathOAuthToken.prototype.setTokenStoreType = function setTokenStoreType(tokenStoreType) {\n      this.tokenStore = TokenStoreManager.getTokenStore(tokenStoreType);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#setToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    * @param {Object} token The OAuth authorization response returned by the API\n    * @returns {Promise} A promise that is resolved or rejected when the storage attempt succeeds or fails\n    *\n    * @description\n    *\n    * Stores the OAuth token data object into storage, relying on its token store\n    * for the storage implementation details. It transforms the snake-cased keys\n    * returned from the API into camel-cased keys when storing the token.\n    */\n    StormpathOAuthToken.prototype.setTokenResponse = function setTokenResponse(token) {\n      var canonicalToken = $normalizeObjectKeys(token);\n      // Store a time at which we should renew the token, subtract off one second to give us some buffer of time\n      canonicalToken.exp = new Date(new Date().setMilliseconds(0)+((token.expires_in-1)*1000));\n      return this.tokenStore.put(STORMPATH_CONFIG.OAUTH_TOKEN_STORAGE_NAME, canonicalToken);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} A promise containing either the resolved token, or a rejection with a reason.\n    *\n    * @description\n    *\n    * Retrieves the OAuth token data object from storage, relying on its set token\n    * store for the loading implementation details. The result will use camel-cased\n    * keys, as noted in\n    * {@link stormpath.oauth.StormpathOAuthToken#setTokenResponse StormpathOAuthToken.setTokenResponse}.\n    */\n    StormpathOAuthToken.prototype.getTokenResponse = function getTokenResponse() {\n      return this.tokenStore.get(STORMPATH_CONFIG.OAUTH_TOKEN_STORAGE_NAME);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#removeToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} A promise indicating whether the operation had succeeded\n    *\n    * @description\n    *\n    * Removes the OAuth token from storage, relying on its set token store for the\n    * implementation details.\n    */\n    StormpathOAuthToken.prototype.removeToken = function removeToken() {\n      return this.tokenStore.remove(STORMPATH_CONFIG.OAUTH_TOKEN_STORAGE_NAME);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getAccessToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} Promise containing the access token, or a rejection in case of failure\n    *\n    * @description\n    *\n    * Retrieves the access token from storage, relying on the token store for implementation.\n    * In case there of storage failure or there being no access token, the result is instead\n    * a rejected promise.\n    */\n    StormpathOAuthToken.prototype.getAccessToken = function getAccessToken() {\n      var self = this;\n      return this.getTokenResponse()\n        .then(function(token) {\n          var tokenType = token && token.tokenType;\n          var accessToken = token && token.accessToken;\n\n          if (!tokenType || !accessToken) {\n            return $q.reject();\n          }\n\n          if (new Date() >= new Date(token.exp)) {\n            var StormpathOAuth = $injector.get('StormpathOAuth');\n            return StormpathOAuth.refresh().then(function(){\n              return self.getAccessToken();\n            });\n          }\n\n          return accessToken;\n        });\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getRefreshToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} Promise containing the refresh token, or a rejection in case of failure\n    *\n    * @description\n    *\n    * Retrieves the refresh token from storage, relying on the token store for implementation.\n    * In case there of storage failure or there being no refresh token, the result is instead\n    * a rejected promise.\n    */\n    StormpathOAuthToken.prototype.getRefreshToken = function getRefreshToken() {\n      return this.getTokenResponse().then(function(token) {\n        if (token) {\n          return token.refreshToken;\n        }\n\n        return $q.reject();\n      });\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getTokenType\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} Promise containing the token type, or a rejection in case of failure\n    *\n    * @description\n    *\n    * Retrieves the token type from storage, relying on the token store for implementation.\n    * In case there of storage failure or there being no token type, the result is instead\n    * a rejected promise.\n    */\n    StormpathOAuthToken.prototype.getTokenType = function getTokenType() {\n      return this.getTokenResponse().then(function(token) {\n        if (token) {\n          return token.tokenType;\n        }\n\n        return $q.reject();\n      });\n    };\n\n    return new StormpathOAuthToken();\n  };\n\n  this.$get.$inject = ['$q', '$normalizeObjectKeys', 'TokenStoreManager', '$injector'];\n}])\n\n/**\n* @ngdoc service\n*\n* @name stormpath.oauth.StormpathOAuthProvider\n* @requires stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n* @description\n*\n* Provides the {@link stormpath.oauth.StormpathOAuth StormpathOAuth}\n* service.\n*/\n.provider('StormpathOAuth', ['STORMPATH_CONFIG', function StormpathOAuthProvider(STORMPATH_CONFIG) {\n\n  var oauthInstance;\n\n  /**\n  * @ngdoc service\n  * @name stormpath.oauth.StormpathOAuth\n  * @requires $q\n  * @requires stormpath.oauth.StormpathOAuthToken\n  *\n  * @description\n  *\n  * A service for managing the OAuth client-side authentication flow logic. It\n  * offers methods for authenticating via the `password` grant type, refreshing\n  * access tokens via refresh tokens, and revoking the current token.\n  */\n  this.$get = function($http, $spFormEncoder, StormpathOAuthToken) {\n    function StormpathOAuth() {\n      this.refreshPromise = null;\n      return this;\n    }\n\n    /**\n    * @ngdoc method\n    * @methodOf stormpath.oauth.StormpathOAuth\n    * @name #authenticate\n    *\n    *\n    * @param {Object} requestData Authentication data object. Expects an email/username and a password field.\n    * @param {Object=} opts Additional request options, (e.g. headers), optional.\n    *\n    * @returns {Promise} A promise containing the authentication response\n    *\n    * @description\n    *\n    * Attempts to authenticate the user, using the password grant flow by default,\n    * although the method can be overriden via the `requestOpts` parameter. If\n    * successful, automatically stores the token using\n    * {@link stormpath.oauth.StormpathOAuthToken#setTokenResponse StormpathOAuthToken.setTokenResponse}.\n    */\n    StormpathOAuth.prototype.authenticate = function authenticate(requestData, extraHeaders) {\n      var self = this;\n      var data = angular.extend({\n        grant_type: 'password'\n      }, requestData);\n\n      var headers = angular.extend({\n        Accept: 'application/json'\n      }, extraHeaders);\n\n      return $http($spFormEncoder.formPost({\n        url: STORMPATH_CONFIG.getUrl('OAUTH_AUTHENTICATION_ENDPOINT'),\n        method: 'POST',\n        headers: headers,\n        data: data\n      })).then(function(response) {\n        StormpathOAuthToken.setTokenResponse(response.data);\n\n        return response;\n      });\n    };\n\n    /**\n    * @ngdoc method\n    * @methodOf stormpath.oauth.StormpathOAuth\n    * @name revoke\n    *\n    * @returns {Promise} A promise containing the revokation response\n    *\n    * @description\n    *\n    * Attempts to revoke the currently active token. If successful, also removes\n    * the token from storage, using\n    * {@link stormpath.oauth.StormpathOAuthToken#removeToken StormpathOAuthToken.removeToken}.\n    * This method is specific to an OAuth workflow, `$auth.endSession()` should be used instead\n    * as it is generc and defers to this method when nedeed.\n    */\n    StormpathOAuth.prototype.revoke = function revoke() {\n\n      return StormpathOAuthToken.getTokenResponse().then(function(token) {\n        var data = {\n          token: token.refreshToken || token.accessToken,\n          token_type_hint: token.refreshToken ? 'refresh_token' : 'access_token'\n        };\n\n        return $http($spFormEncoder.formPost({\n          url: STORMPATH_CONFIG.getUrl('OAUTH_REVOKE_ENDPOINT'),\n          method: 'POST',\n          data: data\n        })).finally(function(response) {\n          StormpathOAuthToken.removeToken();\n\n          return response;\n        });\n      });\n    };\n\n    /**\n     * @ngdoc method\n    * @methodOf stormpath.oauth.StormpathOAuth\n    * @name refresh\n    *\n    * @param {Object=} requestData Additional data to add to the refresh POST request, optional.\n    * @param {Object=} opts Additional request options, (e.g. headers), optional.\n    *\n    * @returns {Promise} A promise containing the refresh attempt response\n    *\n    * @description\n    *\n    * Attempts to refresh the current token, using its refresh token. If successful,\n    * updates the currently stored token using\n    * {@link stormpath.oauth.StormpathOAuthToken#setTokenResponse StormpathOAuthToken.setTokenResponse}\n    * with the response data.\n    */\n    StormpathOAuth.prototype.refresh = function(requestData, extraHeaders) {\n\n      var self = this;\n\n      if (self.refreshPromise) {\n        return self.refreshPromise;\n      }\n\n      return self.refreshPromise = StormpathOAuthToken.getRefreshToken().then(function(refreshToken) {\n        var data = angular.extend({\n          grant_type: 'refresh_token',\n          refresh_token: refreshToken\n        }, requestData);\n\n        var headers = angular.extend({\n          Accept: 'application/json'\n        }, extraHeaders);\n\n        return $http($spFormEncoder.formPost({\n          url: STORMPATH_CONFIG.getUrl('OAUTH_AUTHENTICATION_ENDPOINT'),\n          method: 'POST',\n          headers: headers,\n          data: data\n        })).then(function(response) {\n          StormpathOAuthToken.setTokenResponse(response.data);\n          return response;\n        }).catch(function(response){\n          StormpathOAuthToken.removeToken();\n          return response;\n        }).finally(function (){\n          self.refreshPromise = null;\n        });\n      });\n    };\n\n    if (!oauthInstance) {\n      oauthInstance = new StormpathOAuth();\n    }\n\n    return oauthInstance;\n  };\n\n  this.$get.$inject = ['$http', '$spFormEncoder', 'StormpathOAuthToken'];\n}])\n\n/**\n* @ngdoc service\n* @name stormpath.utils.StormpathOAuthInterceptor\n*\n* @description\n*\n* Processes requests and response errors to avoid manual OAuth flow integration.\n* Adds property Authorization headers to outgoing requests to external domains\n* and handles specific OAuth-based response errors.\n*/\n.factory('StormpathOAuthInterceptor', ['$isCurrentDomain', '$rootScope', '$q', '$injector', 'StormpathOAuthToken', 'STORMPATH_CONFIG',\nfunction($isCurrentDomain, $rootScope, $q, $injector, StormpathOAuthToken, STORMPATH_CONFIG) {\n\n  function StormpathOAuthInterceptor() {}\n\n  /**\n  * @ngdoc method\n  * @name stormpath.utils.StormpathOAuthInterceptor#request\n  * @methodOf stormpath.utils.StormpathOAuthInterceptor\n  *\n  * @param {Object} config $http config object.\n  * @return {Promise} config Promise containing $http config object.\n  *\n  * @description\n  *\n  * Adds the Authorization header on all outgoing request that are going to a\n  * different domain, if the match an expression in the  AUTO_AUTHORIZED_URIS list.\n  */\n\n  StormpathOAuthInterceptor.prototype.request = function request(config) {\n\n    if (STORMPATH_CONFIG.AUTO_AUTHORIZED_URIS.some(function(expr){\n      var regex = expr instanceof RegExp ? expr : new RegExp(expr);\n      return regex.test(config.url);\n    })) {\n      return StormpathOAuthToken.getAccessToken()\n        .then(function(token){\n          config.headers.Authorization = 'Bearer ' + token;\n          return config;\n        }).catch(function(){\n          return config;\n        });\n    }\n\n    return config;\n  };\n\n  return new StormpathOAuthInterceptor();\n}])\n.config(['$httpProvider', function($httpProvider) {\n  $httpProvider.interceptors.push('StormpathOAuthInterceptor');\n}]);\n\n'use strict';\n\nangular.module('stormpath')\n.controller('SpPasswordResetRequestCtrl', ['$scope','$user',function ($scope,$user) {\n  $scope.sent = false;\n  $scope.posting = false;\n  $scope.formModel = {\n    username: ''\n  };\n  $scope.error = null;\n  $scope.submit = function(){\n    $scope.posting = true;\n    $scope.error = null;\n    $user.passwordResetRequest({email: $scope.formModel.email})\n      .then(function(){\n        $scope.sent = true;\n      })\n      .catch(function(err){\n        $scope.error = err.message;\n      }).finally(function(){\n        $scope.posting = false;\n      });\n  };\n}])\n\n.controller('SpPasswordResetCtrl', ['$scope','$location','$user',function ($scope,$location,$user) {\n  var sptoken = $location.search().sptoken;\n  $scope.showVerificationError = false;\n  $scope.verifying = false;\n  $scope.verified = false;\n  $scope.posting = false;\n  $scope.reset = false;\n  $scope.error = null;\n\n  $scope.resendFailed = false;\n  $scope.formModel = {\n    password: '',\n    confirmPassword: ''\n  };\n\n  if(typeof sptoken==='string'){\n    $scope.verifying = true;\n    $user.verifyPasswordResetToken(sptoken)\n      .then(function(){\n        $scope.verified = true;\n      })\n      .catch(function(){\n        $scope.showVerificationError = true;\n      })\n      .finally(function(){\n        $scope.verifying = false;\n      });\n  }else{\n    $scope.showVerificationError = true;\n  }\n  $scope.submit = function(){\n    if($scope.formModel.password!==$scope.formModel.confirmPassword){\n      $scope.error = 'Passwords do not match';\n      return;\n    }\n    $scope.posting = true;\n    $scope.error = null;\n    $scope.showVerificationError = false;\n    $user.resetPassword(sptoken, {password: $scope.formModel.password})\n      .then(function(){\n        $scope.reset = true;\n      })\n      .catch(function(err){\n        $scope.error = err.message;\n      }).finally(function(){\n        $scope.posting = false;\n      });\n  };\n\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spPasswordResetRequestForm:spPasswordResetRequestForm\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n * @description\n *\n * This directive will render a pre-built form which prompts the user for their\n * username/email.  If an account is found, we will send them an email with a\n * password reset link.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-password-reset-request-form></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-password-reset-request-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spPasswordResetRequestForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spPasswordResetRequestForm.tpl.html';\n    },\n    controller: 'SpPasswordResetRequestCtrl'\n  };\n})\n/**\n * @ngdoc directive\n *\n * @name stormpath.spPasswordResetForm:spPasswordResetForm\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n *\n * @description\n *\n * Use this directive on the page that users land on when they click on a password\n * reset link.  To send users a password reset link, see\n * {@link stormpath.spPasswordResetRequestForm:spPasswordResetRequestForm spPasswordResetRequestForm}.\n *\n * This directive will render a password reset form that does the following:\n * * Verifies that the current URL has an `sptoken` in it.  Shows an error if not.\n * * Verifies the given `sptoken` with Stormpath, then:\n *   * If the token is valid, shows a form that allows the user to enter a new password.\n *   * If the token is invalid (it is expired or malformed), we prompt the user to enter\n *     their email address, so that we can try sending them a new link.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-password-reset-form></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-password-reset-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spPasswordResetForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spPasswordResetForm.tpl.html';\n    },\n    controller: 'SpPasswordResetCtrl'\n  };\n});\n\n'use strict';\n\nangular.module('stormpath')\n.controller('SpRegistrationFormCtrl', ['$scope','$user','$auth','$location','$viewModel','$injector', function ($scope,$user,$auth,$location,$viewModel, $injector) {\n  $scope.formModel = (typeof $scope.formModel==='object') ? $scope.formModel : {};\n  $scope.created = false;\n  $scope.enabled = false;\n  $scope.creating = false;\n  $scope.authenticating = false;\n  $scope.viewModel = null;\n\n  $viewModel.getRegisterModel().then(function (model) {\n\n    model.accountStores = model.accountStores.filter(function (accountStore) {\n      return accountStore.authorizeUri && accountStore.authorizeUri !== null;\n    });\n\n    $scope.viewModel = model;\n  }).catch(function (err) {\n    throw new Error('Could not load login view model from back-end: ' + err.message);\n  });\n\n  $scope.submit = function(){\n    $scope.creating = true;\n    $scope.error = null;\n    $user.create($scope.formModel)\n      .then(function(account){\n        $scope.created = true;\n        $scope.enabled = account.status === 'ENABLED';\n        if($scope.enabled && $scope.autoLogin){\n          $scope.authenticating = true;\n          $auth.authenticate({\n            username: $scope.formModel.email,\n            password: $scope.formModel.password\n          })\n          .then(function(){\n            var $state = $injector.has('$state') ? $injector.get('$state') : null;\n            if($scope.postLoginState && $state){\n              $state.go($scope.postLoginState);\n            }\n            else if($scope.postLoginPath){\n              $location.path($scope.postLoginPath);\n            }\n          })\n          .catch(function(err){\n            $scope.error = err.message;\n          })\n          .finally(function(){\n            $scope.authenticating = false;\n            $scope.creating = false;\n          });\n        }else{\n          $scope.creating = false;\n        }\n      })\n      .catch(function(err){\n        $scope.creating = false;\n        $scope.error = err.message;\n      });\n  };\n}])\n\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spRegistrationForm:spRegistrationForm\n *\n * @param {boolean} autoLogin\n *\n * Default `false`. Automatically authenticate the user\n * after creation.  This makes a call to\n * {@link stormpath.authService.$auth#methods_authenticate $auth.authenticate}, which will\n * trigger the event {@link stormpath.authService.$auth#events_$authenticated $authenticated}.\n * This is not possible if the email verification workflow is enabled on the directory that\n * the account is created in.\n *\n * @param {string} postLoginState\n *\n * If using the `autoLogin` option, you can specify the name of a UI state that the user\n * should be redirected to after they successfully have registered.  This is a UI Router\n * integration, and requires that module.\n *\n * @param {string} postLoginPath\n *\n * If using the `autoLogin` option, you can specify the path that the user\n * should be sent to after registration.  This value is passed to\n * `$location.path()` and does not require a specific routing module.\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n *\n * @description\n *\n * This directive will render a pre-built user registration form with the following\n * fields:\n *  * First Name\n *  * Last Name\n *  * Email\n *  * Password\n *\n * # Customizing the Form Fields\n *\n * Our library will make a JSON GET request to the `/register` endpoint on your\n * server, and it expects to receive a view model that describes the form and\n * it's fields.  As such, you will define your custom registration fields in\n * your server-side configuration.  Please see the relevant documentation:\n *\n * * Node.js: [Express-Stormpath - Registration](https://docs.stormpath.com/nodejs/express/latest/registration.html)\n * * PHP: [Stormpath Laravel - Registration](https://docs.stormpath.com/php/laravel/latest/registration.html)\n * * All other frameworks: please see the server integration guide or contact\n *   [support@stormpath.com](support@stormpath.com) for assistance.\n *\n * # Customizing the Form Template\n *\n * If you would like to modify the HTML template that renders our form, you can\n * do that as well.  Here is what you'll need to do:\n *\n * * Create a new view file in your application.\n * * Copy our default template HTML code into your file, found here:\n * <a href=\"https://github.com/stormpath/stormpath-sdk-angularjs/blob/master/src/spRegistrationForm.tpl.html\" target=\"_blank\">spRegistrationForm.tpl.html</a>.\n * * Modify the template to fit your needs, making sure to use `formModel.<FIELD>` as the\n * value for `ng-model` where `.<FIELD>` is the name of the field you want to set on\n * the new account (such as `middleName`).\n * * Use the `template-url` option on the directive to point to your new view file.\n *\n * Any form fields you supply that are not one of the default fields (first\n * name, last name) will need to be defined in the view model (see above) and\n * will be automatically placed into the new account's customa data object.\n *\n * # Email Verification\n *\n * If you are using the email verification workflow, the default template has a message,\n * which will be shown to the user, telling them that they need to check their email\n * for verification.\n *\n * If you are NOT using the email verification workflow, you can, optionally,\n * automatically login the user and redirect them to a UI state in your application.\n * See the options below.\n *\n * # Server Interaction\n *\n * This directive makes a call to\n * {@link stormpath.userService.$user#methods_create $user.create()}\n * when it is ready to POST the form to the server. Please see that method\n * for more information.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-registration-form post-login-state=\"main\"></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-registration-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spRegistrationForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spRegistrationForm.tpl.html';\n    },\n    controller: 'SpRegistrationFormCtrl',\n    link: function(scope,element,attrs){\n      scope.autoLogin = attrs.autoLogin==='true';\n      scope.postLoginPath = attrs.postLoginPath || '';\n      scope.postLoginState = attrs.postLoginState || '';\n    }\n  };\n});\n(function() {\n  'use strict';\n\n/**\n * @ngdoc overview\n *\n * @name  stormpath.socialLoginService\n *\n * @description\n *\n * This module provides the {@link stormpath.socialLoginService.$socialLogin $socialLogin} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\n\n /**\n  * @ngdoc object\n  *\n  * @name stormpath.socialLoginService.$socialLogin\n  *\n  * @description\n  *\n  * The social login service provides a generic authorization interface through\n  * the Stormpath social login interface.\n  */\n  function SocialLoginService(STORMPATH_CONFIG, $encodeQueryParams, $getLocalUrl, $http, $window) {\n    this.providersPromise = null;\n    this.STORMPATH_CONFIG = STORMPATH_CONFIG;\n    this.$encodeQueryParams = $encodeQueryParams;\n    this.$getLocalUrl = $getLocalUrl;\n    this.$http = $http;\n    this.$window = $window;\n  }\n\n  /**\n  * @ngdoc method\n  *\n  * @name authorize\n  * @methodOf stormpath.socialLoginService.$socialLogin\n  * @description\n  *\n  * Authorizes the user using a social authentication provider. This method starts\n  * the redirect flow that attempts to authenticate the user, and, if successful,\n  * ends in the redirect uri configured via {@link STORMPATH_CONFIG.SOCIAL_LOGIN_REDIRECT_URI}.\n  *\n  * @param {String} accountStoreHref\n  * The HREF of the account store (directory) that is set up to provide the social\n  * authentication service.\n  *\n  * @param {Object} options\n  * Additional options (query parameters) to send with the authentication request.\n  *\n  */\n  SocialLoginService.prototype.authorize = function(accountStore, options) {\n    var requestParams = angular.extend({\n      response_type: this.STORMPATH_CONFIG.SOCIAL_LOGIN_RESPONSE_TYPE,\n      account_store_href: accountStore.href,\n      redirect_uri: this.$getLocalUrl(this.STORMPATH_CONFIG.SOCIAL_LOGIN_REDIRECT_URI)\n    }, options);\n\n    var queryParams = this.$encodeQueryParams(requestParams);\n    var socialAuthUri = accountStore.authorizeUri + queryParams;\n\n    this.$window.location = socialAuthUri;\n  };\n\n  angular.module('stormpath.socialLogin', ['stormpath.CONFIG', 'stormpath.utils'])\n\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.socialLoginService.$socialLoginProvider\n   *\n   * @description\n   *\n   * Provides the {@link stormpath.socialLoginService.$socialLogin $socialLogin} service.\n   *\n   * Currently, this provider does not have any configuration methods.\n   */\n  .config(['$injector', 'STORMPATH_CONFIG', function $socialLoginProvider($injector, STORMPATH_CONFIG) {\n    var socialLoginFactory = ['$encodeQueryParams', '$http', '$window', '$getLocalUrl', function socialLoginFactory($encodeQueryParams, $http, $window, $getLocalUrl) {\n      return new SocialLoginService(STORMPATH_CONFIG, $encodeQueryParams, $getLocalUrl, $http, $window);\n    }];\n\n    $injector.get('$provide').factory(STORMPATH_CONFIG.SOCIAL_LOGIN_SERVICE_NAME, socialLoginFactory);\n  }])\n\n  /**\n   * @ngdoc directive\n   *\n   * @name stormpath.spSocialLogin:spSocialLogin\n   *\n   * @description\n   *\n   * Add this directive to a button or link in order to authenticate using a social provider.\n   * The value should be the account store HREF a social provider, such as Google or Facebook.\n   *\n   * The `sp-name` field must be set to the provider ID of the corresponding provider, e.g.\n   * `google` or `facebook`.\n   *\n   * Any additional fields can be specified as an object, via the `sp-options` field. These\n   * options will additionally be augmented (and overriden) by the options set for the given\n   * provider (determined by value of `sp-name`) in {@link STORMPATH_CONFIG.SOCIAL_LOGIN_OPTIONS}.\n   *\n   * {@link http://docs.stormpath.com/guides/social-integrations/}\n   *\n   * @example\n   *\n   * <pre>\n   * <div class=\"container\">\n   *   <button sp-social-login=\"http://url.example/facebook-href\" sp-name=\"facebook\" sp-options=\"{scope: 'email'}\">Login with Facebook</button>\n   * </div>\n   * </pre>\n   */\n  .directive('spSocialLogin', ['$viewModel', '$auth', '$http', '$injector', 'STORMPATH_CONFIG', function($viewModel, $auth, $http, $injector, STORMPATH_CONFIG) {\n    return {\n      link: function(scope, element, attrs) {\n        var accountStore = scope.$eval(attrs.spSocialLogin);\n        var blacklist = ['href', 'providerId', 'clientId'];\n        var social = $injector.get(STORMPATH_CONFIG.SOCIAL_LOGIN_SERVICE_NAME);\n\n        scope.providerName = accountStore.provider.providerId;\n\n        element.bind('click', function() {\n\n          var cleanOptions = {};\n\n          angular.forEach(accountStore.provider, function(value, key) {\n            if (value && blacklist.indexOf(key) !== -1) {\n              cleanOptions[key] = value;\n            }\n          });\n\n          cleanOptions = angular.extend(\n            cleanOptions,\n            STORMPATH_CONFIG.getSocialLoginConfiguration(accountStore.provider.providerId)\n          );\n\n          social.authorize(accountStore, cleanOptions);\n        });\n      }\n    };\n  }])\n\n  /**\n  * @private\n  *\n  * @ngdoc service\n  * @name stormpath.socialLogin.$processSocialAuthToken\n  * @description\n  *\n  * Executes the flow for processing social authentication tokens returned from\n  * the social login authentication redirect flow. If the token is present, it\n  * is used to authenticate the user using the `stormpath_token` grant type.\n  *\n  * Appropriate authentication success or failure events are broadcast when the\n  * authentication concludes.\n  *\n  * If the token is not present in the URL query parameters, the function returns\n  * a resolved promise immediatelly.\n  */\n  .factory('$processSocialAuthToken', ['STORMPATH_CONFIG', '$parseUrl', '$window', '$injector', '$q', '$rootScope',\n    function(STORMPATH_CONFIG, $parseUrl, $window, $injector, $q, $rootScope) {\n      return function processSocialAuthToken() {\n        var parsedUrl = $parseUrl($window.location.href);\n\n        // If this field is present, this means that we have been redirected here\n        // from a social login flow\n        if (parsedUrl.search.jwtResponse) {\n          var AuthService = $injector.get(STORMPATH_CONFIG.AUTH_SERVICE_NAME);\n          return AuthService.authenticate({\n            grant_type: 'stormpath_token',\n            token: parsedUrl.search.jwtResponse\n          }).then(function() {\n            // Clears the URL of the token in both hashbang and HTML5 mode\n            $window.location.search = '';\n\n            $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME)\n          }).catch(function(err) {\n            $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_FAILURE_EVENT_NAME);\n            throw err;\n          });\n        }\n\n        return $q.resolve();\n      };\n    }]);\n}());\n\n'use strict';\n\n/**\n* @ngdoc overview\n*\n* @name stormpath.tokenStore\n*\n* @description\n*\n* This module provides a global access point for registering and fetching token\n* store mechanisms, as used by the {@link stormpath.oauth} module.\n*/\n\n/**\n* @ngdoc object\n* @interface\n* @name stormpath.tokenStore.TokenStore\n*\n* @description\n* A token store implementation. It allows simple key-value pair storing, fetching,\n* and deleting. Its methods may be synchronous, but must always return promises.\n*/\n\n/**\n* @ngdoc method\n* @name stormpath.tokenStore.TokenStore#put\n* @methodOf stormpath.tokenStore.TokenStore\n*\n* @param {String} name The name under which to store a value.\n* @param {Any} value The string representation of a value.\n* @returns {Promise} Indication of success\n*\n* @description\n*\n* Stores a string value in a key-value store.\n*/\n\n/**\n* @ngdoc method\n* @name stormpath.tokenStore.TokenStore#get\n* @methodOf stormpath.tokenStore.TokenStore\n*\n* @param {String} name The name for which to retrieve a value.\n* @returns {Promise} The resolved value retrieved from the store, or a rejection with a reason.\n*\n* @description\n*\n* Retrieves a value from a key-value store.\n*/\n\n/**\n* @ngdoc method\n* @name stormpath.tokenStore.TokenStore#remove\n* @methodOf stormpath.tokenStore.TokenStore\n*\n* @param {String} name The name for which to remove a value.\n* @returns {Promise} Indication of success. Should resolve if there is no value to remove.\n*\n* @description\n*\n* Remove a value from a key-value store.\n*/\n\nangular.module('storpath.tokenStore', ['stormpath.CONFIG'])\n\n/**\n* @ngdoc service\n*\n* @name stormpath.tokenStore.TokenStoreManagerProvider\n*\n* @description\n*\n* Provides the {@link stormpath.tokenStore.TokenStoreManager TokenStoreManager} service.\n*/\n.provider('TokenStoreManager', function() {\n  var tokenStores = {};\n\n  /**\n  * @ngdoc object\n  *\n  * @name stormpath.tokenStore.TokenStoreManager\n  *\n  * @description\n  *\n  * This service provides methods for registering token stores (with duck-typed\n  * validation), as well as retrieving them by name.\n  *\n  * Token store implementations must implement the\n  * {@link stormpath.tokenStore.TokenStore TokenStore interface}.\n  *\n  * All token stores are expected to satisfy the following contract:\n  *   - Instances must have a `put` method that takes a key and a value, stores them, and returns a promise indicating success\n  *   - Instances must have a `get` method that takes a key and returns a promise containing the value for the given key, or a rejection with a reason\n  *   - Instances must have a `remove` method that takes a key and removes the value, returning the result as a promise\n  *\n  * See {@link stormpath.tokenStore.LocalStorageTokenStore LocalStorageTokenStore}\n  * for an example of an implementation.\n  *\n  * @example\n  *\n  * <pre>\n  *   angular.module('app')\n  *     .run(['$q', 'TokenStoreManager', function($q, TokenStoreManager) {\n  *       // Can also be provided by a service/factory for better code organisation\n  *       var myStore = {\n  *         data: {},\n  *         get: function get(key) {\n  *           return this.data[key] ? $q.resolve(this.data[key]) : $q.reject();\n  *         },\n  *         put: function put(key, value) {\n  *           this.data[key] = value;\n  *           return $q.resolve();\n  *         },\n  *         remove: function remove(key) {\n  *           delete this.data[key];\n  *           return $q.resolve();\n  *         }\n  *       };\n  *\n  *       TokenStoreManager.registerTokenStore('basicStore', myStore);\n  *\n  *       var alsoMyStore = TokenStoreManager.getTokenStore('basicStore');\n  *     }]);\n  * </pre>\n  */\n  this.$get = function $get() {\n    return {\n      /**\n      * @ngdoc method\n      * @name stormpath.tokenStore.TokenStoreManager#registerTokenStore\n      *\n      * @methodOf stormpath.tokenStore.TokenStoreManager\n      *\n      * @param {String} name The name under which to store the token store implementation\n      * @param {TokenStore} tokenStore A concrete {@link stormpath.tokenStore.TokenStore TokenStore}\n      *\n      * @throws {Error} tokenStore must satisfy the token store contract methods (get, put, remove).\n      */\n      registerTokenStore: function registerTokenStore(name, tokenStore) {\n        var requiredMethods = ['get', 'put', 'remove'];\n\n        var isValid = tokenStore && requiredMethods.reduce(function(valid, method) {\n          return valid && angular.isFunction(tokenStore[method]);\n        }, true);\n\n        if (!isValid) {\n          throw new Error('Invalid token store. `get`, `put` and `remove` methods must be implemented');\n        }\n\n        tokenStores[name] = tokenStore;\n      },\n      /**\n      * @ngdoc method\n      * @name stormpath.tokenStore.TokenStoreManager#getTokenStore\n      *\n      * @methodOf stormpath.tokenStore.TokenStoreManager\n      *\n      * @param {String} name The name of the token store implementation.\n      * @returns {TokenStore} The token store implementation stored under that name\n      * @throws {Error} When no token store is present for that name.\n      */\n      getTokenStore: function getTokenStore(name) {\n        if (angular.isUndefined(tokenStores[name])) {\n          throw new Error('Unrecognised token store: ' + name);\n        }\n\n        return tokenStores[name];\n      }\n    };\n  };\n})\n\n/**\n* @ngdoc service\n* @name stormpath.tokenStore.LocalStorageTokenStore\n* @augments stormpath.tokenStore.TokenStore\n*\n* @description\n*\n* Implements token storage via browser localStorage.\n*/\n.factory('LocalStorageTokenStore', ['$q', function($q) {\n  function LocalStorageTokenStore() {\n    this._checkAvailability();\n  }\n\n  // Checks whether the current environment supports localStorage and sets the\n  // internal state accordingly\n  LocalStorageTokenStore.prototype._checkAvailability = function _checkAvailability() {\n    if (typeof localStorage === undefined) {\n      this.hasLocalStorage = false;\n    } else {\n      try {\n        localStorage.setItem('sp:feature_test', 'test');\n\n        if (localStorage.getItem('sp:feature_test') === 'test') {\n          localStorage.removeItem('sp:feature_test');\n          this.hasLocalStorage = true;\n        } else {\n          this.hasLocalStorage = false;\n        }\n      } catch (e) {\n        this.hasLocalStorage = false;\n      }\n    }\n  };\n\n  // Provides uniform rejection method for when localStorage is not supported\n  LocalStorageTokenStore.prototype._notImplementedError = function _notImplementedError() {\n    return $q.reject({\n      error: {\n        message: 'Local storage not supported in this environment'\n      }\n    });\n  };\n\n  /**\n  * @ngdoc method\n  * @name stormpath.tokenStore.LocalStorageTokenStore#put\n  * @methodOf stormpath.tokenStore.LocalStorageTokenStore\n  *\n  * @param {String} name The name under which to store a value.\n  * @param {Any} value The string representation of a value.\n  * @returns {Promise} Indication of success\n  *\n  * @description\n  *\n  * Attempts to store a key-value pair using the localStorage API.\n  */\n  LocalStorageTokenStore.prototype.put = function put(key, value) {\n    if (!this.hasLocalStorage) {\n      return this._notImplementedError();\n    }\n\n    var stringValue;\n\n    try {\n      stringValue = JSON.stringify(value);\n    } catch (e) {\n      return $q.reject(e);\n    }\n\n    localStorage.setItem(key, stringValue);\n    return $q.resolve();\n  };\n\n  /**\n  * @ngdoc method\n  * @name stormpath.tokenStore.LocalStorageTokenStore#get\n  * @methodOf stormpath.tokenStore.LocalStorageTokenStore\n  *\n  * @param {String} name The name for which to retrieve a value.\n  * @returns {Promise} Resolved with value or rejected if local storage is unsupported, or value not present.\n  *\n  * @description\n  *\n  * Attempts to retrieve a value for a given key using the localStorage API.\n  */\n  LocalStorageTokenStore.prototype.get = function get(key) {\n    if (!this.hasLocalStorage) {\n      return this._notImplementedError();\n    }\n\n    var value = localStorage.getItem(key);\n\n    if (angular.isDefined(value)) {\n      try {\n        return $q.resolve(JSON.parse(value));\n      } catch (e) {\n        return $q.reject(e);\n      }\n    }\n\n    return $q.reject(new Error('Token not found'));\n  };\n\n  /**\n  * @ngdoc method\n  * @name stormpath.tokenStore.LocalStorageTokenStore#remove\n  * @methodOf stormpath.tokenStore.LocalStorageTokenStore\n  *\n  * @param {String} name The name for which to remove the value.\n  * @returns {Promise} Indication of success\n  *\n  * @description\n  *\n  * Attempts to remove a value for a key from store using the localStorage API.\n  */\n  LocalStorageTokenStore.prototype.remove = function remove(key) {\n    if (!this.hasLocalStorage) {\n      return this._notImplementedError();\n    }\n\n    localStorage.removeItem(key);\n    return $q.resolve();\n  };\n\n  return new LocalStorageTokenStore();\n}])\n\n// Register the basic localStorage provider when run\n.run(['TokenStoreManager', 'LocalStorageTokenStore',\nfunction(TokenStoreManager, LocalStorageTokenStore) {\n  TokenStoreManager.registerTokenStore('localStorage', LocalStorageTokenStore);\n}]);\n\n'use strict';\n/**\n * @ngdoc overview\n *\n * @name stormpath.userService\n *\n * @description\n *\n * This module provides the {@link stormpath.userService.$user $user} service.\n */\n\n/**\n * @ngdoc object\n *\n * @name stormpath.userService.$userProvider\n *\n * @description\n *\n * Provides the {@link stormpath.userService.$user $user} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\n\nangular.module('stormpath.userService',['stormpath.CONFIG', 'stormpath.utils', 'stormpath.socialLogin'])\n.provider('$user', [function $userProvider(){\n\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.userService.$user\n   *\n   * @description\n   *\n   * Use this service to get the current user and do access control checks\n   * on the user.\n   */\n\n  function User(data){\n    var self = this;\n    Object.keys(data).map(function(k){\n      self[k] = data[k];\n    });\n  }\n  /**\n  * This method may change in the future, do not use.\n  * Please use the `ifUserInGroup` directive instead\n  */\n  User.prototype.inGroup = function inGroup(groupName) {\n    return this.groups.items.filter(function(group){\n      return group.name === groupName;\n    }).length >0;\n  };\n  /**\n  * This method may change in the future, do not use.\n  * Please use the `ifUserInGroup` directive instead\n  */\n  User.prototype.matchesGroupExpression = function matchesGroupExpression(regex) {\n    return this.groups.items.filter(function(group){\n      return regex.test(group.name);\n    }).length >0;\n  };\n  /**\n  * This method may change in the future, do not use.\n  * Please use the `ifUserInGroup` directive instead\n  */\n  User.prototype.groupTest = function groupTest(expr) {\n    if(expr instanceof RegExp && this.matchesGroupExpression(expr)){\n      return true;\n    }else if(this.inGroup(expr)){\n      return true;\n    }else{\n      return false;\n    }\n  };\n\n  this.$get = [\n    '$q','$http','STORMPATH_CONFIG','$rootScope','$spFormEncoder','$spErrorTransformer', '$processSocialAuthToken',\n    function userServiceFactory($q,$http,STORMPATH_CONFIG,$rootScope,$spFormEncoder,$spErrorTransformer, $processSocialAuthToken){\n      function UserService(){\n        this.cachedUserOp = null;\n\n        /**\n          * @ngdoc property\n          *\n          * @name currentUser\n          *\n          * @propertyOf stormpath.userService.$user\n          *\n          * @description\n          *\n          * Retains the result of the last call to {@link stormpath.userService.$user#methods_get $user.get()}.\n          * This property is set after every resolution of the {@link stormpath.userService.$user#methods_get $user.get()} promise.\n          *\n          * If the user state is unknown (while {@link stormpath.userService.$user#methods_get $user.get()}\n          * is waiting to be resolved), this value is `null`.\n          *\n          * If the call to {@link stormpath.userService.$user#methods_get $user.get()} has resolved, one of the following will happen:\n          * * If the user is not logged in, this value will be `false`.\n          * * If the user is logged in, this value will be the account object of the user.\n          *\n          */\n\n        this.currentUser = null;\n        return this;\n      }\n      UserService.prototype.create = function(accountData){\n        /**\n         * @ngdoc function\n         *\n         * @name create\n         *\n         * @methodOf stormpath.userService.$user\n         *\n         * @param {Object} accountData\n         *\n         * An object literal for passing the data\n         * to the new account.\n         *\n         * Required fields:\n         * * `givenName` - the user's first name\n         * * `surname` - the user's last name\n         * * `email` - the email address of the user\n         * * `password` - the password that the user wishes to use for their\n         * account.  Must meet the password requirements that you have specified\n         * on the directory that this account will be created in.\n         *\n         * @returns {promise}\n         *\n         * A promise representing the operation to create a\n         * new user.  If an error occurs (duplicate email, weak password), the\n         * promise will be rejected and the http response will be passed.\n         * If the operation is successful, the promise\n         * will be resolved with a boolean `enabled` value.\n         *\n         * * If `true`, the account's status is Enabled and you can proceed with authenticating the user.\n         *\n         * * If `false`, the account's status is Unverified.\n         * This will be the case when you have enabled the email verification workflow on the directory of this\n         * account.\n         *\n         * @description\n         *\n         * Attempts to create a new user by submitting the given `accountData` as\n         * JSON to `/register`.  The POST endpoint can be modified via the\n         * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_REGISTER_URI REGISTER_URI}\n         * config option.\n         *\n         * @example\n         *\n         * <pre>\n         * $user.create(accountData)\n         *   .then(function(account){\n         *     if(account.status === 'ENABLED'){\n         *       // The account is enabled and ready to use\n         *     }else if(account.status === 'UNVERIFIED'){\n         *       // The account requires email verification\n         *     }\n         *   })\n         *   .catch(function(err){\n         *     // Show the error message to the user\n         *     $scope.error = err.message;\n         *   });\n         * </pre>\n         */\n\n        return $http({\n          url: STORMPATH_CONFIG.getUrl('REGISTER_URI'),\n          method: 'POST',\n          data: accountData\n        })\n        .then(function(response){\n          var account = response.data.account || response.data;\n          registeredEvent(account);\n          return $q.resolve(account);\n        },function(httpResponse){\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        });\n\n      };\n      UserService.prototype.get = function get(bypassCache) {\n        /**\n         * @ngdoc function\n         *\n         * @name get\n         *\n         * @methodOf stormpath.userService.$user\n         *\n         * @param {Boolean} [bypassCache=false]\n         *\n         * By default, the UserService will cache the user object after it is\n         * retrieved the first time.  Specify `true` if you need to bypass this\n         * cache, e.g. after updating the user's custom data.\n         *\n         * @returns {promise}\n         *\n         * A promise representing the operation to get the current user data.\n         *\n         * @description\n         *\n         * Attempt to get the current user.  Returns a promise.  If the user\n         * is authenticated, the promise will be resolved with the user object.\n         * If the user is not authenticated, the promise will be rejected and\n         * passed the error response from the $http service.\n         *\n         * If you cannot make use of the promise, you can also observe the\n         * {@link $notLoggedin $notLoggedin} or {@link $currentUser $currentUser}\n         * events.  They are emitted when this method has a success or failure.\n         *\n         * The result of this operation will be cached on the {@link stormpath.userService.$user#properties_currentuser $user.currentUser}\n         * property.\n         *\n         * The user object is a Stormpath Account object, which is wrapped by a\n         * {@link eh User} type.  It is fetched from the `/me` endpoint on your\n         * server, which is provided by our framework integrations.\n         *\n         * @example\n         *\n         * <pre>\n         * var myApp = angular.module('myApp', ['stormpath']);\n         *\n         * myApp.controller('MyAppCtrl', function ($scope, $user) {\n         *   $user.get()\n         *     .then(function (user) {\n         *       console.log('The current user is', user);\n         *     })\n         *     .catch(function (error) {\n         *       console.log('Error getting user', error);\n         *     });\n         * });\n         * </pre>\n         *\n         */\n        var op = $q.defer();\n        var self = this;\n\n        if (self.cachedUserOp) {\n          return self.cachedUserOp.promise;\n        }\n\n        if (self.currentUser !== null && self.currentUser!==false && bypassCache!==true) {\n          op.resolve(self.currentUser);\n          return op.promise;\n        }\n\n        self.cachedUserOp = op;\n        var beforeLoad = self.currentUser ? $q.resolve() : $processSocialAuthToken();\n\n        return beforeLoad.then(function() {\n          $http.get(STORMPATH_CONFIG.getUrl('CURRENT_USER_URI')).then(function(response) {\n            self.cachedUserOp = null;\n            self.currentUser = new User(response.data.account || response.data);\n            currentUserEvent(self.currentUser);\n            op.resolve(self.currentUser);\n          }, function(response) {\n            self.currentUser = false;\n            if (response.status===401) {\n              notLoggedInEvent();\n            }\n            self.cachedUserOp = null;\n            op.reject(response);\n          });\n          return op.promise;\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name resendVerificationEmail\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to resend a verification token\n       * to the given email address.  Will resolve, even if the email address\n       * does not exist.  If rejected there was a network error.\n       *\n       * @description\n       *\n       * Re-sends the verification email to the account specified by the\n       * username or email address.\n       *\n       * @param  {Object} data\n       *\n       * An object literal for passing the username or email.\n       * ```\n       * {\n       *   username: 'email address or username'\n       * }\n       * ```\n       */\n      UserService.prototype.resendVerificationEmail = function resendVerificationEmail(data){\n        return $http({\n          method: 'POST',\n          url: STORMPATH_CONFIG.getUrl('EMAIL_VERIFICATION_ENDPOINT'),\n          data: data\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name verify\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to verify the given\n       * email verification token token.  If resolved the account has been\n       * verified and can be used for login.  If rejected the token is expired\n       * or has already been used.\n       *\n       * @param  {String} sptoken\n       *\n       * The value of the `sptoken` that was sent by email to the user\n       *\n       * @description\n       *\n       * Verifies a new account, using the `sptoken` that was sent to the user\n       * by email.\n       */\n      UserService.prototype.verify = function verify(token){\n        return $http({\n          url: STORMPATH_CONFIG.getUrl('EMAIL_VERIFICATION_ENDPOINT') + '?sptoken='+token\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name verifyPasswordResetToken\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * A $http promise representing the operation to verify the given password\n       * reset token token.  If resolved, the token can be used.  If rejected\n       * the token cannot be used.\n       *\n       * @description\n       *\n       * Verifies a password reset token that was sent to the user by email.\n       * If valid, the token can be used to reset the user's password.  If not\n       * valid it means that the token has expired or has already been used.\n       *\n       * Use this method to verify the token, before asking the user to specify\n       * a new password.  If the token is invalid the user must ask for another.\n       *\n       * @param  {String} sptoken\n       *\n       * The `sptoken` that was delivered to the user by email\n       */\n      UserService.prototype.verifyPasswordResetToken = function verifyPasswordResetToken(token){\n        return $http({\n          url: STORMPATH_CONFIG.getUrl('CHANGE_PASSWORD_ENDPOINT')+'?sptoken='+token\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name passwordResetRequest\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to generate a password\n       * reset token for the given email address.  Will resolve, even if the\n       * email address does not exist.  If rejected there was a network error.\n       *\n       * @description\n       *\n       * Triggers a password reset email to the given username or email address.\n       *\n       * @param  {Object} data\n       *\n       * An object literal for passing the email address.\n       * ```\n       * {\n       *   email: 'email address of the user'\n       * }\n       * ```\n       */\n      UserService.prototype.passwordResetRequest = function passwordResetRequest(data){\n        return $http({\n          method: 'POST',\n          url: STORMPATH_CONFIG.getUrl('FORGOT_PASSWORD_ENDPOINT'),\n          data: data\n        })\n        .catch(function(httpResponse){\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name resetPassword\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to reset the password and\n       * consume the token.  If resolved the password was successfully changed,\n       * if rejected the token is invalid or the posted password does not meet\n       * the password strength rules of the directory.\n       *\n       * @description\n       *\n       * Resets a user's password, using a token that was emailed to the user.\n       *\n       * @param {String} token\n       *\n       * The `sptoken` that was sent to the user via email.\n       *\n       * @param  {Object} data\n       *\n       * An object literal for passing the new password.  Must follow this\n       * format:\n       * ```\n       * {\n       *   password: 'the new password'\n       * }\n       * ```\n       */\n      UserService.prototype.resetPassword = function resetPassword(token,data){\n        data.sptoken = token;\n        return $http({\n          method: 'POST',\n          url:STORMPATH_CONFIG.getUrl('CHANGE_PASSWORD_ENDPOINT'),\n          data: data\n        })\n        .catch(function(httpResponse){\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        });\n      };\n      function registeredEvent(account){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.userService.$user#$registered\n         *\n         * @eventOf stormpath.userService.$user\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {account} account\n         *\n         * The object of the account that was created.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.userService.$user#methods_create $user.create()}\n         * is successful.  The account object is returned, and you can inspec\n         * the account's status to know if email verification is required.\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.REGISTERED_EVENT_NAME,account);\n      }\n      function currentUserEvent(user){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.userService.$user#$currentUser\n         *\n         * @eventOf stormpath.userService.$user\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {User} user\n         *\n         * The current user object.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.userService.$user#methods_get $user.get()}\n         * and provides the user object as the second parameter.\n         *\n         * See the next section, the $notLoggeInEvent, for example usage.\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.GET_USER_EVENT,user);\n      }\n      function notLoggedInEvent(){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.userService.$user#$notLoggedIn\n         *\n         * @eventOf stormpath.userService.$user\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.userService.$user#methods_get $user.get()}\n         * results in an authentication failure.\n         *\n         * This event is useful for situations where you want to trigger\n         * the call to get the current user, but need to respond to it\n         * from some other place in your application.  An example could be,\n         * during application bootstrap, you make a single call to get the current\n         * user from the run function, then react to it inside your\n         * application controller.\n         *\n         * @example\n         *\n         * <pre>\n         * var myApp = angular.module('myApp', ['stormpath']);\n         * myApp.run(function($user){\n         *   //\n         *   // Once our app is ready to run, trigger a call to $user.get()\n         *   // We can then do other things while we wait for the result\n         *   //\n         *   $user.get();\n         * });\n         *\n         * myApp.controller('MyAppCtrl', function ($scope, $rootScope) {\n         *   $scope.isVisible = false; // Wait for authentication\n         *   $rootScope.$on('$notLoggedIn',function(){\n         *      $state.$go('login');\n         *   });\n         *   $rootScope.$on('$currentUser',function(e,user){\n         *      $scope.isVisible = true;\n         *   });\n         *\n         * });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.NOT_LOGGED_IN_EVENT);\n      }\n\n      var userService = new UserService();\n      $rootScope.$on(STORMPATH_CONFIG.SESSION_END_EVENT,function(){\n        userService.currentUser = false;\n      });\n      return userService;\n    }\n  ];\n}]);\n\n'use strict';\n\n/**\n * This module and factory are intentionally excluded from NG Docs.\n *\n * The factory is an internal utility used to check whether an URL is on the\n * same domain on which the SPA is hosted.\n */\n\nangular.module('stormpath.utils', ['stormpath.CONFIG'])\n.factory('$isCurrentDomain', ['$window', function($window) {\n  return function(url) {\n    var link = $window.document.createElement('a');\n    link.href = url;\n\n    return (link.host === \"\") || $window.location.host === link.host.replace(/:443$/, \"\");\n  };\n}])\n.constant('$spHeaders', {\n  // The placeholders in the value are replaced by the `grunt dist` command.\n  'X-Stormpath-Agent': 'stormpath-sdk-angularjs/2.0.1' + ' angularjs/' + angular.version.full\n})\n.provider('$spErrorTransformer', [function $spErrorTransformer(){\n  /**\n   * This service is intentionally excluded from NG Docs.\n   *\n   * It is an internal utility for producing error objects from $http response\n   * errors.\n   */\n\n  this.$get = [\n    function formEncoderServiceFactory(){\n\n      function ErrorTransformerService(){\n\n      }\n\n      ErrorTransformerService.prototype.transformError = function transformError(httpResponse){\n        var errorMessage = null;\n\n        if (httpResponse.data) {\n          errorMessage = httpResponse.data.message || httpResponse.data.error;\n        }\n\n        if (!errorMessage) {\n          errorMessage = 'An error occured when communicating with the server.';\n        }\n\n        var error = new Error(errorMessage);\n\n        error.httpResponse = httpResponse;\n        error.statusCode = httpResponse.status;\n        return error;\n      };\n\n      return new ErrorTransformerService();\n    }\n  ];\n}])\n.provider('$spFormEncoder', [function $spFormEncoder(){\n  /**\n   * This service is intentionally excluded from NG Docs.\n   * It is an internal utility.\n   */\n\n  this.$get = [\n    function formEncoderServiceFactory(){\n\n      function FormEncoderService(){\n        var encoder = new UrlEncodedFormParser();\n        this.encodeUrlForm = encoder.encode.bind(encoder);\n        return this;\n      }\n\n      FormEncoderService.prototype.formPost = function formPost(httpRequest){\n        var h = httpRequest.headers ? httpRequest.headers : (httpRequest.headers = {});\n        h['Content-Type'] = 'application/x-www-form-urlencoded';\n        httpRequest.data = this.encodeUrlForm(httpRequest.data);\n        return httpRequest;\n      };\n\n      function UrlEncodedFormParser(){\n\n        // Copy & modify from https://github.com/hapijs/qs/blob/master/lib/stringify.js\n\n        this.delimiter = '&';\n        this.arrayPrefixGenerators = {\n          brackets: function (prefix) {\n            return prefix + '[]';\n          },\n          indices: function (prefix, key) {\n            return prefix + '[' + key + ']';\n          },\n          repeat: function (prefix) {\n            return prefix;\n          }\n        };\n        return this;\n      }\n      UrlEncodedFormParser.prototype.stringify = function stringify(obj, prefix, generateArrayPrefix) {\n\n        if (obj instanceof Date) {\n          obj = obj.toISOString();\n        }\n        else if (obj === null) {\n          obj = '';\n        }\n\n        if (typeof obj === 'string' ||\n          typeof obj === 'number' ||\n          typeof obj === 'boolean') {\n\n          return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];\n        }\n\n        var values = [];\n\n        if (typeof obj === 'undefined') {\n          return values;\n        }\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          if (Array.isArray(obj)) {\n            values = values.concat(this.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));\n          }\n          else {\n            values = values.concat(this.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));\n          }\n        }\n\n        return values;\n      };\n      UrlEncodedFormParser.prototype.encode = function encode(obj, options) {\n\n        options = options || {};\n        var delimiter = typeof options.delimiter === 'undefined' ? this.delimiter : options.delimiter;\n\n        var keys = [];\n\n        if (typeof obj !== 'object' ||\n          obj === null) {\n\n          return '';\n        }\n\n        var arrayFormat;\n        if (options.arrayFormat in this.arrayPrefixGenerators) {\n          arrayFormat = options.arrayFormat;\n        }\n        else if ('indices' in options) {\n          arrayFormat = options.indices ? 'indices' : 'repeat';\n        }\n        else {\n          arrayFormat = 'indices';\n        }\n\n        var generateArrayPrefix = this.arrayPrefixGenerators[arrayFormat];\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          keys = keys.concat(this.stringify(obj[key], key, generateArrayPrefix));\n        }\n\n        return keys.join(delimiter);\n      };\n\n      return new FormEncoderService();\n    }\n  ];\n}])\n/**\n* Intentionally excluded from the NG Docs.\n*\n* Shallow-transforms snake-cased keys in an object into camelCased keys\n*/\n.factory('$normalizeObjectKeys', function() {\n  return function normalizeObjectKeys(obj) {\n    var camelCasedObj = {};\n\n    Object.keys(obj).forEach(function(key) {\n      if (obj.hasOwnProperty(key)) {\n        var camelCasedKey = key.replace(/_([A-Za-z])/g, function(all, char) {\n          return char.toUpperCase();\n        });\n\n        camelCasedObj[camelCasedKey] = obj[key];\n      }\n    });\n\n    return camelCasedObj;\n  };\n})\n\n.factory('$encodeQueryParams', function() {\n  return function encodeQueryParams(obj) {\n    if (!angular.isObject(obj)) {\n      return '';\n    }\n\n    var query = Object.keys(obj).map(function(key) {\n      return encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]);\n    }).join('&');\n\n    return query ? ('?' + query) : query;\n  };\n})\n\n.factory('$decodeQueryParams', function() {\n  return function decodeQueryParams(str) {\n    if (!angular.isString(str) || str.length === 0) {\n      return {};\n    }\n\n    var params = {};\n\n    str.substr(1).split('&').forEach(function(pair) {\n      var parts = pair.split('=');\n      params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);\n    });\n\n    return params;\n  };\n})\n\n.factory('$parseUrl', ['$decodeQueryParams', function($decodeQueryParams) {\n  return function parseUrl(url) {\n    var parser = document.createElement('a');\n    parser.href = url;\n\n    return {\n      protocol: parser.protocol,\n      hash: parser.hash,\n      host: parser.hostname,\n      port: parser.port,\n      pathname: parser.pathname,\n      query: parser.search,\n      search: $decodeQueryParams(parser.search)\n    };\n  };\n}])\n\n.factory('$getLocalUrl', ['$location', '$parseUrl', function($location, $parseUrl) {\n\n  return function(uri) {\n    if (uri && uri.charAt(0) !== '/') {\n      var parsedUri = $parseUrl(uri);\n      uri = parsedUri.pathname + parsedUri.query + parsedUri.hash;\n    }\n\n    return $location.protocol()\n      + '://'\n      + $location.host()\n      + ($location.port() ? (':' + $location.port()) : '')\n      + uri;\n\n  };\n}]);\n\n(function () {\n  'use strict';\n\n  function ViewModelService($http, STORMPATH_CONFIG) {\n    this.$http = $http;\n    this.STORMPATH_CONFIG = STORMPATH_CONFIG;\n  }\n\n  ViewModelService.prototype.getLoginModel = function getLoginModel() {\n    return this.$http.get(this.STORMPATH_CONFIG.getUrl('AUTHENTICATION_ENDPOINT'), {\n      headers: {\n        'Accept': 'application/json'\n      }\n    }).then(function (response) {\n      return response.data;\n    });\n  };\n\n  ViewModelService.prototype.getRegisterModel = function getRegisterModel() {\n    return this.$http.get(this.STORMPATH_CONFIG.getUrl('REGISTER_URI'), {\n      headers: {\n        'Accept': 'application/json'\n      }\n    }).then(function (response) {\n      return response.data;\n    });\n  };\n\n  angular.module('stormpath.viewModelService', ['stormpath.utils'])\n  .provider('$viewModel', function () {\n    this.$get = ['$http', 'STORMPATH_CONFIG', function viewModelFactory($http, STORMPATH_CONFIG) {\n      return new ViewModelService($http, STORMPATH_CONFIG);\n    }];\n  });\n}());\n})(window, window.angular);"
  },
  {
    "path": "dist/stormpath-sdk-angularjs.tpls.js",
    "content": "/**\n * stormpath-sdk-angularjs\n * Copyright Stormpath, Inc. 2017\n * \n * @version v2.0.1-dev-2017-04-04\n * @link https://github.com/stormpath/stormpath-sdk-angularjs\n * @license Apache-2.0\n */\n\n/* commonjs package manager support (eg componentjs) */\nif (typeof module !== \"undefined\" && typeof exports !== \"undefined\" && module.exports === exports){\n  module.exports = 'stormpath.templates';\n}\n\n(function (window, angular, undefined) {\n\nangular.module('stormpath.templates', ['spEmailVerification.tpl.html', 'spLoginForm.tpl.html', 'spPasswordResetForm.tpl.html', 'spPasswordResetRequestForm.tpl.html', 'spRegistrationForm.tpl.html']);\n\nangular.module(\"spEmailVerification.tpl.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"spEmailVerification.tpl.html\",\n    \"<div class=row><div class=\\\"col-sm-offset-4 col-xs-12 col-sm-4\\\"><p ng-show=verifying class=\\\"alert alert-warning\\\">We are verifying your account</p><p ng-show=verified class=\\\"alert alert-success\\\">Your account has has been verified! <a href=/login>Login Now.</a></p><p ng-show=reVerificationSent class=\\\"alert alert-success\\\">We have sent a new verification message to your email address, please check your email for this message.</p><div ng-show=showVerificationError class=\\\"alert alert-danger\\\">This email verification link is not valid. If you need us to re-send an email verification message, please enter your email address or username below.</div><div ng-show=resendFailed class=\\\"alert alert-danger\\\">Sorry, there was a problem with that email or username. Please try again.</div></div></div><div class=row><div class=col-xs-12><form class=form-horizontal ng-show=\\\"needsReVerification && !reVerificationSent\\\" ng-submit=submit()><div class=form-group><label for=spEmail class=\\\"col-xs-12 col-sm-4 control-label\\\">Email or Username</label><div class=\\\"col-xs-12 col-sm-4\\\"><input class=form-control id=spUsername ng-model=formModel.username placeholder=\\\"Username or Email\\\" ng-disabled=posting></div></div><div class=form-group><div class=\\\"col-sm-offset-4 col-xs-12\\\"><p class=text-danger ng-show=error ng-bind=error></p><button type=submit class=\\\"btn btn-primary\\\" ng-disabled=posting>Re-Send Verification</button></div></div></form></div></div>\");\n}]);\n\nangular.module(\"spLoginForm.tpl.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"spLoginForm.tpl.html\",\n    \"<style>.btn.btn-social {\\n\" +\n    \"    margin-right: 7px;\\n\" +\n    \"    min-width: 100px;\\n\" +\n    \"  }\\n\" +\n    \"\\n\" +\n    \"  .btn.btn-facebook {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #3B5998;\\n\" +\n    \"    border-color: #37528C;\\n\" +\n    \"  }\\n\" +\n    \"  .btn.btn-facebook:hover,\\n\" +\n    \"  .btn.btn-facebook:focus {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #2F487B;\\n\" +\n    \"    border-color: #2F487B;\\n\" +\n    \"  }\\n\" +\n    \"\\n\" +\n    \"  .btn.btn-google {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #dc4e41;\\n\" +\n    \"    border-color: #C1453A;\\n\" +\n    \"  }\\n\" +\n    \"  .btn.btn-google:hover,\\n\" +\n    \"  .btn.btn-google:focus {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #C74539;\\n\" +\n    \"    border-color: #AF4138;\\n\" +\n    \"  }\\n\" +\n    \"\\n\" +\n    \"  .sp-loading {\\n\" +\n    \"    text-align: center;\\n\" +\n    \"  }</style><div class=row><div class=col-xs-12><div ng-show=!viewModel class=sp-loading>Loading...</div><form class=form-horizontal ng-hide=\\\"accepted || !viewModel\\\" ng-submit=submit()><div class=form-group ng-repeat=\\\"field in viewModel.form.fields\\\"><label for=sp-{{field.name}} class=\\\"col-xs-12 col-sm-4 control-label\\\">{{field.label}}</label><div class=\\\"col-xs-12 col-sm-4\\\"><input class=form-control name={{field.name}} id=sp-{{field.name}} type={{field.type}} ng-model=formModel[field.name] placeholder={{field.placeholder}} ng-disabled=posting ng-required=field.required></div></div><div class=form-group><div class=\\\"col-sm-offset-4 col-sm-4\\\"><p class=text-danger ng-show=error ng-bind=error></p><button type=submit class=\\\"btn btn-primary\\\" ng-disabled=posting>Login</button> <a href=/forgot class=pull-right>Forgot Password</a></div></div><div class=form-group ng-show=viewModel.accountStores.length><div class=\\\"col-sm-offset-4 col-sm-4\\\"><p>Or login with:</p><button ng-repeat=\\\"accountStore in viewModel.accountStores\\\" type=button class=\\\"btn btn-social btn-{{accountStore.provider.providerId}}\\\" sp-social-login=accountStore sp-options={{accountStore.provider}} style=\\\"text-transform: capitalize\\\">{{providerName}}</button></div></div></form></div></div>\");\n}]);\n\nangular.module(\"spPasswordResetForm.tpl.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"spPasswordResetForm.tpl.html\",\n    \"<div class=row><div class=\\\"col-sm-offset-4 col-xs-12 col-sm-4\\\"><p ng-show=verifying class=\\\"alert alert-warning text-center\\\">We are verifying this link</p><p class=\\\"alert alert-success\\\" ng-show=reset>Your new password has been set. Please <a href=/login>Login Now</a>.</p><div ng-show=showVerificationError class=\\\"alert alert-danger\\\">This password reset link is not valid. You may request another link by <a href=/forgot>clicking here</a>.</div></div></div><div class=row><div class=col-xs-12><form class=form-horizontal ng-show=\\\"verified && !reset\\\" ng-submit=submit()><div class=form-group><label for=spEmail class=\\\"col-xs-12 col-sm-4 control-label\\\">New Password</label><div class=\\\"col-xs-12 col-sm-4\\\"><input class=form-control id=spUsername ng-model=formModel.password placeholder=\\\"New Password\\\" type=password ng-disabled=posting></div></div><div class=form-group><label for=spEmail class=\\\"col-xs-12 col-sm-4 control-label\\\">Confirm New Password</label><div class=\\\"col-xs-12 col-sm-4\\\"><input class=form-control id=spUsername ng-model=formModel.confirmPassword placeholder=\\\"Confirm New Password\\\" type=password ng-disabled=posting></div></div><div class=form-group><div class=\\\"col-sm-offset-4 col-sm-4\\\"><p class=\\\"alert alert-danger\\\" ng-show=error ng-bind=error></p><button type=submit class=\\\"btn btn-primary\\\" ng-disabled=posting>Set New Password</button></div></div></form></div></div>\");\n}]);\n\nangular.module(\"spPasswordResetRequestForm.tpl.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"spPasswordResetRequestForm.tpl.html\",\n    \"<div class=row><div class=\\\"col-sm-offset-4 col-xs-12 col-sm-4\\\"><p ng-show=sent class=\\\"alert alert-success\\\">We have sent a password reset link to the email address of the account that you specified. Please check your email for this message, then click on the link.</p><p ng-show=sent class=pull-right><a href=/login>Back to Login</a></p><div ng-show=error class=\\\"alert alert-danger\\\" ng-bind=error></div></div></div><div class=row><div class=col-xs-12><form class=form-horizontal ng-hide=sent ng-submit=submit()><div class=form-group><label for=spEmail class=\\\"col-xs-12 col-sm-4 control-label\\\">Email or Username</label><div class=\\\"col-xs-12 col-sm-4\\\"><input class=form-control id=spEmail ng-model=formModel.email placeholder=\\\"Your Email Address\\\" ng-disabled=posting></div></div><div class=form-group><div class=\\\"col-sm-offset-4 col-xs-12\\\"><p class=text-danger ng-show=error ng-bind=error></p><button type=submit class=\\\"btn btn-primary\\\" ng-disabled=posting>Request Password Reset</button></div></div></form></div></div>\");\n}]);\n\nangular.module(\"spRegistrationForm.tpl.html\", []).run([\"$templateCache\", function ($templateCache) {\n  $templateCache.put(\"spRegistrationForm.tpl.html\",\n    \"<style>.btn.btn-social {\\n\" +\n    \"    margin-right: 7px;\\n\" +\n    \"    min-width: 100px;\\n\" +\n    \"  }\\n\" +\n    \"\\n\" +\n    \"  .btn.btn-facebook {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #3B5998;\\n\" +\n    \"    border-color: #37528C;\\n\" +\n    \"  }\\n\" +\n    \"  .btn.btn-facebook:hover,\\n\" +\n    \"  .btn.btn-facebook:focus {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #2F487B;\\n\" +\n    \"    border-color: #2F487B;\\n\" +\n    \"  }\\n\" +\n    \"\\n\" +\n    \"  .btn.btn-google {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #dc4e41;\\n\" +\n    \"    border-color: #C1453A;\\n\" +\n    \"  }\\n\" +\n    \"  .btn.btn-google:hover,\\n\" +\n    \"  .btn.btn-google:focus {\\n\" +\n    \"    color: white;\\n\" +\n    \"    background-color: #C74539;\\n\" +\n    \"    border-color: #AF4138;\\n\" +\n    \"  }\\n\" +\n    \"\\n\" +\n    \"  .sp-loading {\\n\" +\n    \"    text-align: center;\\n\" +\n    \"  }</style><div class=row><div class=\\\"col-sm-offset-4 col-xs-12 col-sm-4\\\"><p class=\\\"alert alert-success\\\" ng-show=\\\"created && !enabled\\\">Your account has been created. Please check your email for a verification link.</p><p ng-show=\\\"created && !enabled\\\" class=pull-right><a href=/login>Back to Login</a></p><p class=\\\"alert alert-success\\\" ng-show=\\\"created && enabled && !authenticating\\\">Your account has been created. <a href=/login>Login Now</a>.</p></div></div><div class=row><div class=col-xs-12><div ng-show=!viewModel class=sp-loading>Loading...</div><form class=form-horizontal ng-hide=\\\"!viewModel || (created && !authenticating)\\\" ng-submit=submit()><div class=form-group ng-repeat=\\\"field in viewModel.form.fields\\\"><label for=sp-{{field.name}} class=\\\"col-xs-12 col-sm-4 control-label\\\">{{field.label}}</label><div class=\\\"col-xs-12 col-sm-4\\\"><input class=form-control name={{field.name}} id=sp-{{field.name}} type={{field.type}} ng-model=formModel[field.name] placeholder={{field.placeholder}} ng-disabled=creating ng-required=field.required></div></div><div class=form-group><div class=\\\"col-sm-offset-4 col-sm-4\\\"><p class=\\\"alert alert-danger\\\" ng-show=error ng-bind=error></p><button type=submit class=\\\"btn btn-primary\\\" ng-disabled=creating>Register</button></div></div><div class=form-group ng-show=viewModel.accountStores.length><div class=\\\"col-sm-offset-4 col-sm-4\\\"><p>Or register with:</p><button ng-repeat=\\\"accountStore in viewModel.accountStores\\\" type=button class=\\\"btn btn-social btn-{{accountStore.provider.providerId}}\\\" sp-social-login=accountStore sp-options={{accountStore.provider}} style=\\\"text-transform: capitalize\\\">{{providerName}}</button></div></div></form></div></div>\");\n}]);\n})(window, window.angular);\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/stormpath-sdk-angular.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/stormpath-sdk-angular.qhc\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/stormpath-sdk-angular\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/stormpath-sdk-angular\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "docs/render",
    "content": "#!/bin/bash\n\nmake clean\nmake html\n"
  },
  {
    "path": "docs/source/access_control.rst",
    "content": ".. _access_control:\n\nAccess Control\n===================\n\nParts of your application may only be available to certain users.\nStormpath provides Groups, which is a great way to segment users.\n\nWe provide some functionality, which makes it easy to make UI decisions\nby looking at the groups that the account is a member of.\n\n\nServer Configuration\n--------------------------\n\nOur Angular SDK knows who the current user is by accessing the ``/me`` route on\nyour server.  This route needs to return the account object, with its groups\nexpanded.  If you are using our Express.js library you can enable this with the\n``expand`` option:\n\n.. code-block:: javascript\n\n    app.use(ExpressStormpath.init(app,{\n      website: true,\n      expand: {\n        groups: true\n      },\n      web: {\n        spaRoot: path.join(__dirname, '..','client','index.html')\n      }\n    }));\n\n\n\nUI State Control\n--------------------------\n\nIf you wish to prevent access to an entire UI State, you can define\na group authorization check in the state configuration.  In this example,\nwe are requiring that the user be in the Admin group::\n\n    // Require a user to be in the admins group in order to see this state\n    $stateProvider\n      .state('admin', {\n        url: '/admin',\n        controller: 'AdminCtrl',\n        sp: {\n          authorize: {\n            group: 'admins'\n          }\n        }\n      });\n\nFor more examples, see the `SpStateConfig documentation`_.\n\nHelper Directives\n--------------------------\n\nIf you need to show or hide specific elements in response to group state,\nyou can use the `ifUserInGroup`_ and `ifUserNotInGroup`_ directives. In\nthis example, we show a link to the Admin view if the user is in the Admin\ngroup.  If the user is not in the Admin group, we let them know that they\nneed to request access:\n\n.. code-block:: html\n\n  <ul class=\"nav navbar-nav\">\n    <li if-user-in-group=\"admins\">\n      <a ng-href=\"/admin\">Admin Console</a>\n    </li>\n    <li if-user>\n      <a ui-sref=\"main\" sp-logout>Logout</a>\n    </li>\n  </ul>\n  <div class=\"container\">\n    <h3>Hello, {{user.fullName}}</h3>\n    <p if-user-not-in-group=\"admins\">\n      If you require Administrator access, please contact us.\n    </p>\n  </div>\n\nAPI Security\n--------------------------\n\nDon't forget to secure your API!  While we provide these convenient\nmethods in Angular, you need to protect your server APIs as well.\nIf you are using our Express SDK, you can use the `Authorization Middleware`_\nto help with this.\n\n\n.. _ifUserInGroup: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserInGroup:ifUserInGroup\n.. _ifUserNotInGroup: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserNotInGroup:ifUserNotInGroup\n.. _Authorization Middleware: http://docs.stormpath.com/nodejs/express/latest/authorization.html\n.. _SpStateConfig documentation: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.SpStateConfig:SpStateConfig\n"
  },
  {
    "path": "docs/source/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# stormpath-sdk-angular documentation build configuration file, created by\n# sphinx-quickstart on Mon Feb 16 11:15:30 2015.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\nimport sys\nimport os\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#sys.path.insert(0, os.path.abspath('.'))\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = []\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix of source filenames.\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = u'Stormpath AngularJS + Yeoman Guide'\ncopyright = u'2015, Stormpath'\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# The short X.Y version.\nversion = '0.0.2'\n# The full version, including alpha/beta/rc tags.\nrelease = '0.0.2'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#language = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#today = ''\n# Else, today_fmt is used as the format for a strftime call.\n#today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = []\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\nhighlight_language = 'js'\n\n# A list of ignored prefixes for module index sorting.\n#modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n#keep_warnings = False\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\nhtml_theme = 'stormpath'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#html_theme_options = {}\n\n# Add any paths that contain custom themes here, relative to this directory.\nhtml_theme_path = ['_themes']\n\n# The name for this set of Sphinx documents.  If None, it defaults to\n# \"<project> v<release> documentation\".\n#html_title = None\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#html_logo = None\n\n# The name of an image file (within the static path) to use as favicon of the\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\n#html_favicon = None\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#html_extra_path = []\n\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\n# using the given strftime format.\n#html_last_updated_fmt = '%b %d, %Y'\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#html_additional_pages = {}\n\n# If false, no module index is generated.\n#html_domain_indices = True\n\n# If false, no index is generated.\n#html_use_index = True\n\n# If true, the index is split into individual pages for each letter.\n#html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\n#html_show_sourcelink = True\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\n#html_show_sphinx = True\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n#html_file_suffix = None\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'stormpath-sdk-angulardoc'\n\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n# The paper size ('letterpaper' or 'a4paper').\n#'papersize': 'letterpaper',\n\n# The font size ('10pt', '11pt' or '12pt').\n#'pointsize': '10pt',\n\n# Additional stuff for the LaTeX preamble.\n#'preamble': '',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n  ('index', 'stormpath-sdk-angular.tex', u'stormpath-sdk-angular Documentation',\n   u'Stormpath', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#latex_use_parts = False\n\n# If true, show page references after internal links.\n#latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#latex_appendices = []\n\n# If false, no module index is generated.\n#latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    ('index', 'stormpath-sdk-angular', u'stormpath-sdk-angular Documentation',\n     [u'Stormpath'], 1)\n]\n\n# If true, show URL addresses after external links.\n#man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n  ('index', 'stormpath-sdk-angular', u'stormpath-sdk-angular Documentation',\n   u'Stormpath', 'stormpath-sdk-angular', 'One line description of project.',\n   'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#texinfo_appendices = []\n\n# If false, no module index is generated.\n#texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#texinfo_no_detailmenu = False\n"
  },
  {
    "path": "docs/source/configure_angular.rst",
    "content": ".. _configure_angular:\n\nConfigure the Angular Application\n---------------------------------\n\nThere are a few things we need to setup before we can build the\nrest of the application.  We need to add the Stormpath modules as\ndependencies of our application, and we need to configure some of the\nmagic that will happen with the `UI Router`_ module.\n\nAdd Stormpath to the Angular Application\n========================================\n\nWe need to manually declare the Stormpath Angular SDK as a module\nin the Angular application.\n\nOpen the file ``client/app/app.js`` and modify the module list\nto have these two Stormpath dependencies at the end of the list::\n\n    angular.module('dashboardApp', [\n      'ngCookies',\n      'ngResource',\n      'ngSanitize',\n      'ui.router',\n      'stormpath',\n      'stormpath.templates'\n    ])\n\nConfigure the UI Router Integration\n===================================\n\nOur Angular SDK is designed to work with the third-party `UI Router`_ module (support\nfor Angular's built-in router will be coming in a future release).  Before we\nadd anything else to our application, we need to setup the `UI Router`_ integration.\n\n.. note::\n  We *highly* recommend the UI Router module, over the Angular built-in router.  It\n  provides a very good way for organizing your Angular application.\n\nIn the same ``app.js`` file you want to add this run block, place\nit below the ``.config`` block (make sure you move the semicolon\nfrom the config block to the run block)::\n\n\n    .run(function($stormpath){\n      $stormpath.uiRouter({\n        loginState: 'login',\n        defaultPostLoginState: 'main'\n      });\n    });\n\nThis configures the integration to do the following:\n\n* Redirect users to the ``login`` view if they try to access a restricted view. After logging in, they are sent back to the view that they originally requested.\n* Send users to the ``main`` view after login if they have visited the login page directly (they did not try to access a restricted view first).\n\nWith that, we are ready to start working on the views!  Continue to the next section\nwhere we begin by modifying the menu bar to include links for Login and Registration.\n\n.. _UI Router: https://github.com/angular-ui/ui-router\n"
  },
  {
    "path": "docs/source/create_new_project.rst",
    "content": ".. _create_new_project:\n\nCreating a Fullstack Project\n============================\n\nThis part of the guide will walk you through the creation of an AngularJS\nproject from scratch.  We will use `Grunt`_ as a build tool, and `Yeoman`_ as\na scaffolding tool.\n\nWe will use `Node.JS`_ as our backend server with the Stormpath Express SDK.\n\n\nInstalling Node, Grunt, Bower and Yeoman\n----------------------------------------\n\nIf you haven't installed Node.js on your system, you can download it at https://nodejs.org.\n\nThen you need to install `Grunt`_, a tool for helping you build your\nproject.  This must be installed as a global npm package::\n\n    $ npm install -g grunt-cli\n\nThe next tool you need is Yeoman_, a \"scaffolding\" tool (it makes it easy to create\nrepeatable boilerplate code).  This must also be installed as a global NPM package::\n\n    $ npm install -g yo\n\nFinally, we will install `Bower`_, a package manager for front-end applications::\n\n    $ npm install -g bower\n\n.. _Grunt: http://gruntjs.com/\n.. _Bower: http://bower.io/\n.. _Node.JS: http://nodejs.org/\n.. _Yeoman: http://yeoman.io/\n.. _Getting Started Guide: http://gruntjs.com/getting-started\n.. _UI Router: https://github.com/angular-ui/ui-router\n\n\n\nCreate an Angular-Fullstack Project\n-----------------------------------\n\nWe are going to use the `Angular Fullstack Generator <https://github.com/DaftMonk/generator-angular-fullstack>`_.\nIt's going to create _**a lot**_ of files for us; essentially, our entire development environment\nand the seed files for the client and the server.  This is really amazing!\n\nTo use the generator, you need to first install it as a global node module::\n\n    $ npm install -g generator-angular-fullstack\n\nAt this point, you should create a directory for your project and change into it::\n\n    $ mkdir my-angular-project && cd $_\n\nOnce there, we use the generator to create the project.  We need to give our application a\nname (it does not have to be the same as the folder).  Since we are building a basic user\ndashboard for our API, we will call it \"dashboard\"::\n\n    $ yo angular-fullstack dashboard\n\nThe generator will ask you several questions, such as which templating engine to use.  We're sticking\nto vanilla HTML/CSS/JS for this guide. The only opinionated choice we are making is to use the 3rd-party\n`UI Router`_ instead of Angular's default.\nHere are the choices that we made::\n\n    # Client\n\n    ? What would you like to write scripts with? JavaScript\n    ? What would you like to write markup with? HTML\n    ? What would you like to write stylesheets with? CSS\n    ? What Angular router would you like to use? uiRouter\n    ? Would you like to include Bootstrap? Yes\n    ? Would you like to include UI Bootstrap? No\n\n    # Server\n\n    ? Would you like to use mongoDB with Mongoose for data modeling? No\n\nAssuming everything installs OK, you should now have the default project ready to go.  Use this grunt command to start the development server and view the application::\n\n    $ grunt serve\n\nIt should automatically open the following page in your browser:\n\n.. image:: _static/fullstack-new-project.png\n\nInstall the Stormpath Packages\n------------------------------\n\nWe need to add two packages to this project: the `Stormpath Express Module`_ and the `Stormpath Angular SDK`_.\nBecause the Angular SDK is a front-end application, it is managed with `Bower`_.\n\nInstall them with these commands, which will also persist them to your ``package.json`` and ``bower.json`` files::\n\n    $ npm install --save express-stormpath\n    $ bower install --save stormpath-sdk-angularjs\n\nUpgrade Express\n---------------\n\nWe also want to make sure that we are using the latest version of Express. Run\nthe following command to get the latest::\n\n    $ npm i express@latest --save\n\nIn the next section, we will get your Stormpath Tenant information so that we can\ncontinue with the latter sections.\n\nGit Tracking\n------------\nNow would be a good time to start using Git with your project. You can\nstop the server by pressing ``Ctrl+C`` then use the following git commands::\n\n    $ git init\n    $ git add .\n    $ git commit -m \"Begin dashboard app project\"\n\n\n\n.. _Stormpath Admin Console: https://api.stormpath.com\n.. _Stormpath Angular SDK: https://github.com/stormpath/stormpath-sdk-angularjs\n.. _Stormpath Express Module: https://github.com/stormpath/express-stormpath"
  },
  {
    "path": "docs/source/create_tenant.rst",
    "content": ".. _create_tenant:\n\nCreate a Stormpath Tenant\n==============================\n\nIf you have already signed up for Stormpath, you can skip this section and continue\nto the next one (you will still need to fetch your API Keys and App Href that you\nwant to use with this project).\n\nSign up for Stormpath\n---------------------\n\nNow that you're ready to integrate Stormpath, the first thing you'll want to do is\ncreate a new Stormpath account by visiting https://api.stormpath.com/register.\n\nWe'll send you an email verification message, please verify it and then you can\nlogin to the `Stormpath Admin Console`_.\n\nCreate an API Key Pair\n----------------------\n\nOnce you've logged into the `Stormpath Admin Console`_, click the \"Manage API Keys\" button on your home page.\nThis will allow you to generate a new API key and it will prompt you to download your keypair.\n\n.. note::\n    Please keep the API key pair file you just downloaded safe!  These two keys\n    allow you to make Stormpath API requests and should be properly protected.\n\n.. _Stormpath Admin Console: https://api.stormpath.com/login\n\nCreate a Stormpath Application\n------------------------------\n\nNext, you'll want to create a new Stormpath Application.\n\nStormpath allows you to provision any number of \"Applications\".  An \"Application\" is just Stormpath's term for a project.\n\nLet's say you want to build a few separate websites.  One site named\n\"dronewars.com\", and another named \"carswap.com\".  In this case, you'd want to\ncreate two separate Stormpath Applications, one named \"dronewars\" and another\nnamed \"carswap\".  Each Stormpath Application should represent a real life\napplication of some sort.\n\nThe general rule is that you should create one Application per website (or\nproject).  Since we're just getting set up, you'll want to create a single\nApplication.\n\nTo do this, click the \"Applications\" tab in the Stormpath dashboard, then click\n\"Register an Application\" and follow the on-screen instructions.\n\n.. note::\n    Use the default options when creating an Application. This way you'll be\n    able to create users in your new Application without issue.\n"
  },
  {
    "path": "docs/source/customize_menu.rst",
    "content": ".. _customize_menu:\n\nCustomize the Menu\n===================\n\nNow that our Angular application is configured, let's get on with the building!\n\nThe first view we want to work with is the menu bar.  We want to have login\nand registration links, as well as a link to the user profile view that we\nwill be building.\n\nWhen the user is not logged in, we want the following to happen:\n\n * Show a link to the Registration page\n * Show a link to the Login page\n\nBut when they login, we want the following to happen:\n\n * Hide the links to the Registration and Login pages\n * Show a link to the Profile page (we'll build that in a later section)\n * Show a Logout link\n\nModify navbar.html\n--------------------------\n\nOpen the file ``client/components/navbar/navbar.html`` and replace\nthe ``<ul>`` section with this markup:\n\n.. code-block:: html\n\n  <ul class=\"nav navbar-nav\">\n    <li ng-repeat=\"item in menu\" ng-class=\"{active: isActive(item.link)}\">\n        <a ng-href=\"{{item.link}}\">{{item.title}}</a>\n    </li>\n    <li if-user ng-class=\"{active: isActive('/profile')}\">\n        <a ui-sref=\"profile\">Profile</a>\n    </li>\n    <li if-not-user ng-class=\"{active: isActive('/register')}\">\n        <a ui-sref=\"register\">Register</a>\n    </li>\n    <li if-not-user ng-class=\"{active: isActive('/login')}\">\n        <a ui-sref=\"login\">Login</a>\n    </li>\n    <li if-user ng-class=\"{active: isActive('/logout')}\">\n        <a ui-sref=\"main\" sp-logout>Logout</a>\n    </li>\n  </ul>\n\nWe've retained the piece that iterates over the default links, but we also\nadded the new links that we want.  We are using the\n`ifUser`_ and `ifNotUser`_ directives to control the visibility of the links.\n\nYou can reload the app to see these changes, but the links will not work until\nwe complete the following sections in this guide.\n\n.. _ifUser: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUser:ifUser\n.. _ifNotUser: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifNotUser:ifNotUser"
  },
  {
    "path": "docs/source/index.rst",
    "content": ".. stormpath-sdk-angular documentation master file, created by\n   sphinx-quickstart on Mon Feb 16 11:15:30 2015.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to Stormpath's AngularJS + Yeoman Guide!\n=================================================\n\n.. image:: _static/awesome.png\n\nThis guide will show you how to create an Angular application that uses the Stormpath\nUser Management Service to handle user registration and login.  We will show you how to:\n\n* Begin an Angular application from scratch, using Grunt, Yeoman and Bower.\n* Create a simple REST API and secure it with Oauth Access Tokens (JWTs).  We will use Express.js for the server.\n* Control access to views in the Angular application.\n* Fetch information about the user from your API.\n* Render your UI based on the current user state.\n\nReady to get started?  Continue with the :ref:`introduction`.\n\nTable of Contents\n---------------------\n.. toctree::\n   :maxdepth: 2\n\n   introduction\n   create_new_project\n   create_tenant\n   protect_api\n   configure_angular\n   customize_menu\n   login\n   register\n   user_profile\n   password_reset\n   access_control\n   wait_for_user\n   support\n"
  },
  {
    "path": "docs/source/introduction.rst",
    "content": ".. _introduction:\n\nIntroduction\n=============\n\nThe purpose of this guide is to walk you through the creation of an Angular\nproject from scratch, while showing you how to integrate the\n`Stormpath Angular SDK`_ to achieve the following tasks in your Angular\napplication:\n\n* User Login\n* User Registration\n* Password Reset\n* Access Control\n\nIf you're a seasoned AngularJS developer and simply want to explore the\nmodule API, you can visit the `Stormpath AngularJS SDK API Documentation`_.\n\nWhat We're Building\n--------------------\n\nIn this guide we will create a simple API server that our Angular application\nwill use using Node.js.  If you wish to create a server using Java, please see\nour `Java Web App Plugin Guide`_.  For other environments please visit\n`Stormpath Docs`_ to see if we have an integration for you!\n\nBy the end of this guide we will create the following:\n\n**A fullstack project & workflow**.  We're going to create a project with a lot\nof boilerplate code, but don't worry, it's going to be created automatically for\nyou!  This is the power of Yeoman.\n\n**A Node.js server**.  This server will serve the assets for the Angular\napplication.  It will also serve a simple API, which we will secure with\nStormpath.\n\n**An Angular application**.  This will be an HTML5-based application, which\nallows users to register, login, and see their profile.  We will control profile\naccess so that only logged-in users can access that view.\n\nExample Project\n--------------------\n\nAs you follow this tutorial, you will be creating and editing files.  If you're\nuncertain about a certain step, you can compare your code to the example project\nin this folder of the SDK repository:\n\nhttps://github.com/stormpath/stormpath-sdk-angularjs/tree/master/example/dashboard-app\n\n\nHow to get Support\n-------------------\nGetting stuck?  Stormpath is a developer-focused platform.  We want to hear from you!  Reach\nus anytime through one of the following channels:\n\n* Email support: support@stormpath.com\n* Our knowledge base: https://support.stormpath.com/hc/en-us\n* Github: https://github.com/stormpath/stormpath-sdk-angularjs\n\n\n.. _Stormpath Docs: https://docs.stormpath.com\n\n.. _Stormpath Angular SDK: https://github.com/stormpath/stormpath-sdk-angularjs\n\n.. _Stormpath AngularJS SDK API Documentation: https://docs.stormpath.com/angularjs/sdk/\n\n.. _Java Web App Plugin Guide: https://docs.stormpath.com/java/servlet-plugin/"
  },
  {
    "path": "docs/source/login.rst",
    "content": ".. _login:\n\nCreate the Login Form\n=====================\n\nLogin forms are pretty straightforward, why re-invent the wheel? The `Stormpath\nAngular SDK`_ includes a default login form that you can be quickly inserted\ninto your application via an Angular directive.  To use it, we need to create a\nLogin route and a view in our application.\n\nGenerate the /login Route\n-------------------------\n\nWe can use Yeoman to create the Angular route and view at the same time.\n\nStop the server, then run the following command in your project folder::\n\n    $ yo angular-fullstack:route login\n\nIt will ask you the following questions, so just hit enter to choose the defaults for all of them::\n\n    ? Where would you like to create this route? client/app/\n    ? What will the url of your route be? /login\n\nIt will then tell you about the files it has created::\n\n  create client/app/login/login.js\n  create client/app/login/login.controller.js\n  create client/app/login/login.controller.spec.js\n  create client/app/login/login.css\n  create client/app/login/login.html\n\nUse the Login Form Directive\n----------------------------\n\nOpen the file ``client/app/login/login.html`` and then replace\nits contents with the following:\n\n.. code-block:: html\n\n    <div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <h3>Login</h3>\n          <hr>\n        </div>\n      </div>\n      <div sp-login-form></div>\n    </div>\n\nThis is a small bit of HTML markup, which does the following:\n\n* Includes the common menu bar for the application (we customized it in the last section).\n* Sets up some Bootstrap classes so that the page flows nicely.\n* Inserts the default login form via the `spLoginForm`_ directive.\n\nSave that file and restart the server via ``grunt serve``. Now, when you click\nthe Login link, you should now see the login route like this:\n\n.. image:: _static/login_form.png\n\nPerfect!  Now that we have a login form, we also need the ability to register\nfor an account.  Continue on to the next section and we will build a registration form.\n\nIf you want to further customize the look and behavior of the form,\nplease see the API documentation for the `spLoginForm`_ directive.\nThe most useful feature is the ability to specify your own template.\n\n\n.. _spLoginForm: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spLoginForm:spLoginForm\n.. _Stormpath Angular SDK: https://github.com/stormpath/stormpath-sdk-angularjs"
  },
  {
    "path": "docs/source/password_reset.rst",
    "content": ".. _password_reset:\n\nPassword Reset Flow\n===================\n\nStormpath provides a secure solution that allows your users to request a password\nreset token by email.  We send the user a link with a verification token; when\nthey click on this link, they arrive back at your site.  You then validate\nthat this token came from Stormpath and ask the user to set a new password.\n\nThis Angular SDK provides forms that facilitate this process for you.\n\nWe need two separate UI routes for this flow:\n\n* ``/forgot`` will serve a form that asks the user for their email address.  When\n  this form is submitted, we will send the email with a password reset link.\n* ``/reset`` will be the page they land on when they click on the link in their email.\n\n\nGenerate the Routes\n-------------------\n\nUsing the generator command, create a routes for ``forgot`` and ``reset``:\n\n.. code-block:: bash\n\n    $ yo angular-fullstack:route forgot\n\n.. code-block:: bash\n\n    ? Where would you like to create this route? client/app/\n    ? What will the url of your route be? /forgot\n\n.. code-block:: bash\n\n    $ yo angular-fullstack:route reset\n\n.. code-block:: bash\n\n    ? Where would you like to create this route? client/app/\n    ? What will the url of your route be? /reset\n\n\nAdd the sptoken Parameter\n-------------------------\n\nWhen the user clicks on the link in their email, they will be sent to your\napplication with a url parameter called ``sptoken`` - we need to let the UI\nrouter know about this.  Open the file ``client/app/reset/reset.js`` and modify\nthe ``url`` string to include this parameter::\n\n    url: '/reset?sptoken',\n\n\nUse the Password Reset Directives\n---------------------------------\n\nWe want to modify the two views that we created in the last steps.\n\nOpen ``client/app/forgot/forgot.html`` and replace its contents with the following:\n\n.. code-block:: html\n\n    <div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <h3>Forgot Password</h3>\n          <hr>\n        </div>\n      </div>\n      <div sp-password-reset-request-form></div>\n    </div>\n\n\nNext, open ``client/app/reset/reset.html`` and replace its contents with the following:\n\n.. code-block:: html\n\n    <div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <h3>Reset Your Password</h3>\n          <hr>\n        </div>\n      </div>\n      <div sp-password-reset-form></div>\n    </div>\n\n\n\nConfigure the Directory\n-----------------------\n\nIn order to use the password reset feature, you will need to enable it\non the Directory that this account will be created in.  Login to the\n`Stormpath Admin Console`_ and find the Directories tab.  You will see the\nDirectory that was automatically created for the Application.  Click into it,\nfind the Workflows tab, then the Password Reset tab.\n\nYou need to enable the **Password Reset Email** and modify the **Link Base URL**\nto point to your application.  At the moment, that URL will be:\n\n.. code-block:: bash\n\n    http://localhost:9000/reset\n\nDon't forget to press save!\n\nHere is what that screen looks like:\n\n.. image:: _static/directory-password-reset.png\n\n\nTry It, Reset your Password!\n----------------------------\n\nThis form should be fully functional now!  Visit the Login page and you\nwill see a link to the Forgot Password flow.\n\n.. _Stormpath Email Verification: http://docs.stormpath.com/rest/product-guide/#verify-an-email-address\n\n.. _Stormpath Admin Console: https://api.stormpath.com/login"
  },
  {
    "path": "docs/source/protect_api.rst",
    "content": ".. _protect_api:\n\nConfigure the Server\n====================\n\nIn the previous section, :ref:`create_new_project`, we created a simple\nExpress.js server and installed the `Stormpath Express Module`_.  We are going to use that\nSDK to secure the API endpoints in the Express server.\n\n\nSetting Environment Variables\n------------------------------------\n\nThe `Stormpath Express Module`_ needs the API Key and Application information that\nwe collected in the section :ref:`create_tenant`.  We will provide this\ninformation to the SDK by exporting it to the environment.\n\n\nYou can manually export the values to the environment by using the ``export``\nor ``set`` commands in your terminal.\n\n**Unix/Linux/Mac**::\n\n  export STORMPATH_CLIENT_APIKEY_ID=xxxx\n  export STORMPATH_CLIENT_APIKEY_SECRET=xxxx\n  export STORMPATH_APPLICATION_HREF=xxxx\n\n**Windows**::\n\n  set STORMPATH_CLIENT_APIKEY_ID=xxxx\n  set STORMPATH_CLIENT_APIKEY_SECRET=xxxx\n  set STORMPATH_APPLICATION_HREF=xxxx\n\n\n\nRequire the Stormpath Module\n----------------------------\n\nOpen the file ``server/app.js``.  This file is the entry point for our API\nserver and it will run the server.\n\nWe want to initialize the Stormpath middleware and add it before our API\ndeclaration so that the API will be automatically protected.\n\nFirst things first, you need to require the SDK; place the following at the top of the\nfile under the other require statements::\n\n    var ExpressStormpath = require('express-stormpath');\n\nWe're also going to use the ``path``, so you should require the following as well::\n\n   var path = require('path');\n\nThen you want to create an instance of the Stormpath middleware.  You can pass in\noptions, but in our case, we are just going to make a simple call and use all\nthe default options.  Add the following after the ``var app = express();`` statement::\n\n    app.use(ExpressStormpath.init(app,{\n      website: true,\n      web: {\n        spaRoot: path.join(__dirname, '..','client','index.html')\n      }\n    }));\n\nThis block of code will attach Stormpath to your Express application, and let\nStormpath know where the root of your Angular application is (the folder\nwhere all of the Angular assets live).\n\nWe also need to instruct Express to wait for Stormpath to be initialized.  Our\nmodule makes several requests to our API in order to fetch the information that\nit needs to correctly configure your Express application.  Find the\n``server.listen`` statement at the end of the file, and wrap it in an event\nhandler for ``stormpath.ready`` like so::\n\n    app.on('stormpath.ready',function() {\n      // Start server\n      server.listen(config.port, config.ip, function () {\n        console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));\n      });\n    });\n\nProtect Your API Routes\n-----------------------\n\nOpen the file ``server/routes.js``. This file is attaching some routes to the\nExpress application that is setup in ``server/app.js``.  You'll want to require\n``express-stormpath`` again and then use it to secure your API::\n\n    var ExpressStormpath = require('express-stormpath');\n\n    // ..\n\n    app.use('/api/things', ExpressStormpath.loginRequired, require('./api/thing'));\n\nReload the App\n---------------\n\nRestart the server by running ``grunt serve`` again.  You should now see that\nthe features are no longer listed. This is because the endpoint fails to load\nwith a ``401 Unauthorized``. You can see this by looking inside the web console\nin your browser:\n\n.. image:: _static/features-unauthorized.png\n\n\nOur API is now protected from unauthorized, anonymous access.  In the next two\nsections, we will show you how to create a registration form and a login form.\nAt that point, you will be able to login and have access to the API.\n\n.. _Configuration and Config Vars: https://devcenter.heroku.com/articles/config-vars\n.. _Stormpath Express Module: https://github.com/stormpath/express-stormpath"
  },
  {
    "path": "docs/source/register.rst",
    "content": ".. _register:\n\nCreate the Registration Form\n============================\n\nWe want our users to sign up for our service so we need to provide a\nregistration form.  The `Stormpath Angular SDK`_ provides a pre-built\nregistration form that can be inserted with an Angular directive.  When a user\nsubmits this form, it will create a new account for them in the Stormpath\nDirectory that is associated with the Stormpath Application that you created in\nthe :ref:`create_tenant` section.\n\nGenerate the /register Route\n----------------------------\n\nStop the server and run the following command in your project folder:\n\n.. code-block:: bash\n\n    $ yo angular-fullstack:route register\n\nPress enter to accept the defaults options:\n\n.. code-block:: bash\n\n    ? Where would you like to create this route? client/app/\n    ? What will the url of your route be? /register\n\nThe following files will be created:\n\n.. code-block:: bash\n\n    create client/app/register/register.js\n    create client/app/register/register.controller.js\n    create client/app/register/register.controller.spec.js\n    create client/app/register/register.css\n    create client/app/register/register.html\n\n\nAdd the Registration Form Directive\n-----------------------------------\n\nOpen the file ``client/app/register/register.html`` and then replace\nits contents with the following:\n\n.. code-block:: html\n\n    <div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <h3>Registration</h3>\n          <hr>\n        </div>\n      </div>\n      <div sp-registration-form post-login-state=\"main\"></div>\n    </div>\n\nThis HTML markup does the following:\n\n* Includes the common menu bar for the application.\n* Sets up some `Bootstrap`_ classes so that the page flows nicely.\n* Inserts the default registration form via the `spRegistrationForm`_ directive.\n* Declares (on the directive) that we want to send the user to the main page after they register.\n\nSave that file and the browser should auto-reload. You should now\nsee the registration view like this:\n\n.. image:: _static/registration_form.png\n\nIf you want to further customize the look and behavior of the form,\nplease see the API documentation for the\n`spRegistrationForm`_ directive.\nThe most useful feature is the ability to specify your own template.\n\nGenerate the /verify Route\n--------------------------\n\nThe `Stormpath Email Verification`_ feature will allow you to confirm a user's\nidentity by sending them a link that they must click on.\nWe handle all the email and links for you!  (If you don't want to use this\nfeature, you can skip this section.)\n\nHowever, we must have a place for the user to land when they click on that\nlink in their email.  We will implement a default view for this in our application\nand configure the Stormpath Directory accordingly.\n\nThe first thing is to generate another route.  In this situation, we will\ncall the controller ``verify``:\n\n.. code-block:: bash\n\n  $ yo angular-fullstack:route verify\n\n.. code-block:: bash\n\n  ? Where would you like to create this route? client/app/\n  ? What will the url of your route be? /register/verify\n     create client/app/verify/verify.js\n     create client/app/verify/verify.controller.js\n     create client/app/verify/verify.controller.spec.js\n     create client/app/verify/verify.css\n\n\nAdd the sptoken Parameter\n-------------------------\n\nWhen the user clicks on the link in their email, they will be sent to your\napplication with a url parameter called ``sptoken`` - we need to let the UI\nrouter know about this.  Open the file ``client/app/verify/verify.js`` and\nmodify the ``url`` string to include the following parameter:\n\n.. code-block:: js\n\n    url: '/verify?sptoken',\n\n\nUse the Email Verification Directive\n------------------------------------\n\nWe have a pre-built view that shows the necessary informational messages when\nsomeone is trying to complete the email verification process. It will:\n\n* Show a success message and prompt them to login.\n* Allow them to request another email if the link has expired.\n\nOpen the file ``client/app/verify/verify.html`` and\nreplace its contents with the following:\n\n.. code-block:: html\n\n    <div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <h3>Verify Your Account</h3>\n          <hr>\n        </div>\n      </div>\n      <div sp-email-verification></div>\n    </div>\n\nConfigure the Directory\n-----------------------\n\nIn order to use the email verification feature, you will need to enable it\non the Directory that this account will be created in.  Login to the\n`Stormpath Admin Console`_ and find the Directories tab.  You will see the\nDirectory that was automatically created for the Application.  Click into it,\nfind the Workflows tab, and then enable the email verification workflow.\n\nYou should also modify the **Link Base URL** to point\nto your application.  At the moment, that URL will be:\n\n.. code-block:: html\n\n    http://localhost:9000/verify\n\n\nDon't forget to press save!\n\nHere is what that screen looks like:\n\n.. image:: _static/directory_email_verification.png\n\nTry It, Register for an Account!\n--------------------------------\n\nThat's it, really!  Give the form a try.  Once you register for an\naccount, you will be automatically redirected back to the main page.\nYou will also be logged-in automatically, and you will start seeing\nthe list of things again -- remember how we locked it down?  Now that\nyou are authenticated, you are allowed to access that part of the API\nagain.\n\n\nCustomizing the Form Fields\n---------------------------\n\nWhen rendering the registration form, the Stormpath Angular SDK will make a JSON\nGET request to the ``/register`` endpoint on your server, and it expects to\nreceive a view model that describes the form and it's fields.  As such, you will\ndefine your custom registration fields in your server-side configuration. Please\nsee the `Express-Stormpath Registration Documentation`_ for in-depth\ninstructions.\n\nAs an example, we can do the following in `server/app.js`:\n\n.. code-block:: javascript\n\n  app.use(ExpressStormpath.init(app,{\n    web: {\n\n      /* .. Other options */\n\n      register: {\n        form: {\n          fields: {\n            favoriteColor: {\n              enabled: true,\n              label: 'Favorite Color?',\n              placeholder: 'e.g. Blue',\n              required: true,\n              type: 'text'\n            }\n          }\n        }\n      }\n    }\n  }));\n\nWith this custom field configuration, the Stormpath Angular SDK will\nautomatically render this field on your registration form and apply the data to\nthe user's custom data object when they register - cool!\n\nCustomizing the Form Template\n-----------------------------\n\nIf you would like to modify the HTML template that renders our form, you can do\nthat as well.  You'll make use of the ``template-url`` option on the directive.\n\nFor example, create a new file in ``client/app/register/`` and call it\n``my-register.html``.  Copy the contents from our existing ``register.html``\ninto it.  Then add the following markup to it in a place that you like:\n\n.. code-block:: html\n\n  <div class=\"form-group\">\n    <label for=\"favColor\" class=\"col-xs-12 col-sm-4 control-label\">Favorite Color</label>\n    <div class=\"col-xs-12 col-sm-4\">\n      <input type=\"text\" class=\"form-control\" id=\"favColor\" ng-model=\"formModel.favoriteColor\" ng-disabled=\"creating\">\n    </div>\n  </div>\n\nNow, modify your registration form directive and tell it to use the following custom template:\n\n.. code-block:: html\n\n  <div sp-registration-form post-login-state=\"main\" template-url=\"app/register/my-register.html\"></div>\n\nYour registration form should have a new field for entering your favorite color!  This information\nwill go into the ``customData`` object on the Account object.\n\n.. note::\n  You need to ensure that your server-side framework is decoding complex form\n  objects in POST bodies.  If you are using the common ``body-parser`` library, you can\n  enable that with the ``extended`` option::\n\n    app.use(bodyParser.urlencoded({ extended: true }));\n\nFor more information about the registration form, see the  `spRegistrationForm`_ documentation.\n\n.. _Bootstrap: http://getbootstrap.com\n\n.. _Express-Stormpath Registration Documentation: https://docs.stormpath.com/nodejs/express/latest/registration.html\n\n.. _Stormpath Angular SDK: https://github.com/stormpath/stormpath-sdk-angularjs\n\n.. _spRegistrationForm: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.spRegistrationForm:spRegistrationForm\n\n.. _Stormpath Email Verification: http://docs.stormpath.com/rest/product-guide/#verify-an-email-address\n\n.. _Stormpath Admin Console: https://api.stormpath.com/login"
  },
  {
    "path": "docs/source/support.rst",
    "content": ".. _support:\n\nSupport\n==============\n\nWe're here to help if you get stuck.  There are several ways that you an get in\ntouch with a member of our team:\n\n* Join us on our Slack channel: https://talkstormpath.shipit.xyz/\n* Send an email to support@stormpath.com\n* Open a Github Issue for this library: https://github.com/stormpath/stormpath-sdk-angularjs"
  },
  {
    "path": "docs/source/user_profile.rst",
    "content": ".. _user_dashboard:\n\nCreate the Profile View\n=======================\n\nMost user-centric applications have a Profile view where the user can view and\nedit their basic profile information.  In this section, we will show you how to\nmake a *very* simple display of the user's information.  In the next release of\nthis guide, we will show you how to update the user's information, see :ref:`coming_soon`\n\nGenerate the /profile Route\n---------------------------\n\nAlright, one more time!  We're going to use the generator to scaffold the files for us:\n\n.. code-block:: bash\n\n    $ yo angular-fullstack:route profile\n\n.. code-block:: bash\n\n    ? Where would you like to create this route? client/app/\n    ? What will the url of your route be? /profile\n\n\nForce Authentication\n--------------------\n\nThe user must be logged in if they want to see their profile;\notherwise, there is nothing to show!  We want to prevent users\nfrom accessing this page if they are not logged in.  We do\nthat by defining the\n`SpStateConfig <https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.SpStateConfig:SpStateConfig>`_\non the UI state for this route.\n\nOpen the file ``client/app/profile/profile.js`` and modify the\nstate configuration to include the Stormpath state configuration::\n\n    .state('profile', {\n      url: '/profile',\n      templateUrl: 'app/profile/profile.html',\n      controller: 'ProfileCtrl',\n      sp: {\n        authenticate: true\n      }\n    });\n\nCreate the View\n---------------\n\nBecause we have declared ``authenticate: true`` for this state, we\nare guaranteed that the user will always be logged in by the time that\nthis view loads (if the user is not logged in, they are redirected\nto the login page and then back here).\n\nWith that assurance, we can code our template without any complex\nswitches.\nThe Stormpath module will automatically assign the current user\nobject to ``user`` on the Root Scope, so it will always be available\nin your templates.\n\nWe're going to keep this super simple and merely render a user's object as a JSON\nstructure.  Obviously, you'll be doing more than this when your application goes\nlive. :)\n\nOpen the file ``client/app/profile/profile.html`` and then replace\nits contents with the following:\n\n.. code-block:: html\n\n    <div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n    <div class=\"container\">\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <h3>My Profile</h3>\n          <hr>\n        </div>\n\n      </div>\n\n      <div class=\"row\">\n        <div class=\"col-xs-12\">\n          <pre ng-bind=\"user | json\"></pre>\n        </div>\n      </div>\n    </div>\n\nJust like the other pages, we've included our common menu and setup\nsome basic Bootstrap classes.  The ``<pre>`` block will leverage\nAngular's built-in ``json`` filter to show the user object.\n\nTry It Out, See Your Profile!\n-----------------------------\n\nGo back to your browser, make sure you're logged in, and then go to the\nProfile link.  You should now see your user data:\n\n.. image:: _static/profile_view.png\n\n"
  },
  {
    "path": "docs/source/wait_for_user.rst",
    "content": ".. _wait_for_user:\n\nWaiting For User State\n=======================\n\nNow that we have a complete application, you should play around with it!\n\nAs you do, you may find something annoying:  our menu bar has a bit of\na \"flash\" to it; even if we are logged in, it will momentarily show\nas if we are not logged in.  This happens while we're fetching the information\nabout the current user.\n\nYou'll only see this in the main view; you won't see it in the Profile\nview because that is an authenticated route.\n\nHow do we solve this problem?\n\nUse the waitForUser Option\n---------------------------\n\nThe answer is incredibly simple. Just use the ``waitForUser`` option on\nthe state configuration!\n\nWith this option, we'll defer the rendering of the view, but won't\ngo to the login page if the user is not logged in.  We'll continue to\nthe view, but the current user state will be resolved either way.  This\nallows our templates to render properly and immediately once the state\nis known.\n\nOpen the file ``client/app/main/main.js`` and add the option to the\nstate configuration::\n\n    .state('main', {\n      url: '/',\n      templateUrl: 'app/main/main.html',\n      controller: 'MainCtrl',\n      sp:{\n        waitForUser: true\n      }\n    });\n\nThat's it!  When you reload your app, you'll see a white page for a moment\nand then everything will render with the proper user state.\n\nIf you have a complex bootstrap process, and want to show some kind of loading\noverlay while the application is bootstrapping, you may find the\n`ifUserStateUnknown`_\ndirective of use.\n\n.. _ifUserStateUnknown: https://docs.stormpath.com/angularjs/sdk/#/api/stormpath.ifUserStateUnknown:ifUserStateUnknown"
  },
  {
    "path": "example/cors-app/.bowerrc",
    "content": "{\n    \"directory\": \"client/bower_components\"\n}\n"
  },
  {
    "path": "example/cors-app/README.md",
    "content": "# Stormpath Angular + Express + CORS\n\nThis folder contains an example application that is built with the\n[Stormpath Angular SDK][] and [Stormpath Express][].\n\nThis example shows you how to host your Angular application on a different\ndomain from your API service.\n\n#### Running the Example Application\n\n1. To run this application, you will need Bower and Grunt as global packages:\n\n  ```bash\n  npm install -g grunt bower\n  ```\n\n2. Clone this repo to your computer, and enter the directory for this example:\n\n  ```bash\n  git clone https://github.com/stormpath/stormpath-sdk-angularjs.git\n  cd stormpath-sdk-angularjs/example/cors-app\n  ```\n\n3. Install the dependencies:\n\n  ```bash\n  npm install\n  bower install\n  ```\n4. Export your environment variables for your Stormpath Tenant and Application:\n\n  ```bash\n  export STORMPATH_CLIENT_APIKEY_ID=xxx\n  export STORMPATH_CLIENT_APIKEY_SECRET=xxx\n  export STORMPATH_APPLICATION_HREF=xxx\n  ```\n\n5. You *may* need to edit your  `/etc/hosts` file to create aliases for localhost,\n   if so you would add these lines to it:\n\n   ```\n   127.0.0.1  a.localhost\n   127.0.0.1  b.localhost\n   ```\n\n5. Start the server with the node command:\n\n  ```bash\n  node server.js\n  ```\n\n  When the Stormpath client is ready, the website http://a.localhost:3000 will\n  be opened in your Browser.  It will be communicating with your API service\n  which is running on http://b.localhost:4000\n\n\n[Stormpath Angular SDK]: https://github.com/stormpath/stormpath-sdk-angularjs\n[Stormpath Express]: https://github.com/stormpath/stormpath-express\n[Yeoman Guide]: https://docs.stormpath.com/angularjs/guide\n"
  },
  {
    "path": "example/cors-app/bower.json",
    "content": "{\n  \"name\": \"cors-app\",\n  \"homepage\": \"https://github.com/stormpath/stormpath-sdk-angularjs\",\n  \"authors\": [\n    \"Robert <robert@stormpath.com>\"\n  ],\n  \"description\": \"\",\n  \"main\": \"\",\n  \"moduleType\": [],\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"node_modules\",\n    \"bower_components\",\n    \"app/bower_components\",\n    \"test\",\n    \"tests\"\n  ],\n  \"dependencies\": {\n    \"angular\": \"~1.4.7\",\n    \"stormpath-sdk-angularjs\": \"~1.0.0\",\n    \"jquery\": \"~2.1.4\",\n    \"bootstrap\": \"~3.3.5\"\n  }\n}\n"
  },
  {
    "path": "example/cors-app/client/client.js",
    "content": "'use strict';\n\nangular.module('loginApp',[\n  'stormpath',\n  'stormpath.templates'\n])\n.config(['STORMPATH_CONFIG',function (STORMPATH_CONFIG) {\n  /*\n    We tell the Stormpath library that our API service is\n    on the other domain by setting the prefix for all requests\n   */\n  STORMPATH_CONFIG.ENDPOINT_PREFIX = 'http://b.localhost:4000';\n}])\n.controller('ProtectedResourceController',['$scope','$http','$rootScope',function ($scope,$http,$rootScope) {\n  $scope.$on('$currentUser',function () {\n    $http.get('http://b.localhost:4000/api/thing')\n      .then(function (thing) {\n        $scope.thing = thing;\n      });\n  });\n}]);\n\n"
  },
  {
    "path": "example/cors-app/client/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>CORS Demo Application</title>\n  <link rel=\"stylesheet\" href=\"bower_components/bootstrap/dist/css/bootstrap.css\" />\n  <script type=\"text/javascript\" src=\"bower_components/jquery/dist/jquery.js\"></script>\n  <script type=\"text/javascript\" src=\"bower_components/angular/angular.js\"></script>\n  <script type=\"text/javascript\" src=\"bower_components/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.js\"></script>\n  <script type=\"text/javascript\" src=\"bower_components/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.tpls.js\"></script>\n  <script type=\"text/javascript\" src=\"client.js\"></script>\n</head>\n<body>\n<div class=\"container\" ng-app=\"loginApp\">\n  <br/>\n  <div if-user ng-controller=\"ProtectedResourceController\">\n    <p><a class=\"btn btn-primary\" sp-logout>Logout</a></p>\n    <pre ng-bind=\"thing ? (thing | json) : 'Fetching thing..'\"></pre>\n  </div>\n  <div if-user-state-known>\n    <div if-not-user sp-login-form></div>\n  </div>\n\n</div>\n</body>\n</html>"
  },
  {
    "path": "example/cors-app/package.json",
    "content": "{\n  \"name\": \"cors-app\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"server.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"start\": \"node server.js\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"cors\": \"^2.7.1\",\n    \"express\": \"^4.13.3\",\n    \"express-stormpath\": \"^3.0.0\",\n    \"open\": \"0.0.5\"\n  }\n}\n"
  },
  {
    "path": "example/cors-app/server.js",
    "content": "var cors = require('cors');\nvar express = require('express');\nvar stormpath = require('express-stormpath');\nvar open = require('open');\nvar path = require('path');\n\n/*\n  The websiteService is a naive Express app, it's only\n  purpose is to serve the assets for our Angular application\n */\n\nvar websiteDomain = 'http://a.localhost:3000';\n\nvar websiteService = express();\n\nwebsiteService.use('/',express.static(path.join(__dirname,'client')));\n\nwebsiteService.listen(3000,function () {\n  open(websiteDomain);  // Opens the Angular app in your browser\n});\n\n/*\n  The apiService is your API that you want to protect with\n  Stormpath.  We use the CORS module to whitelist the website\n  domain, thus allowing it to communicate with the API domain\n */\n\nvar apiService = express();\n\napiService.use(cors({\n  origin: websiteDomain,\n  credentials: true\n}));\n\napiService.use(stormpath.init(apiService,{ }));\n\n/*\n  We use the loginRequired middleware, as that will assert\n  that the Angular client has authenticated and has valid\n  OAuth tokens in the cookies that were stpored on the API domain\n */\n\napiService.get('/api/thing', stormpath.loginRequired, function (req,res) {\n  res.json(req.user);\n});\n\napiService.on('stormpath.ready',function() {\n  apiService.listen(4000);\n});"
  },
  {
    "path": "example/dashboard-app/.bowerrc",
    "content": "{\n    \"directory\": \"client/bower_components\"\n}\n"
  },
  {
    "path": "example/dashboard-app/.buildignore",
    "content": "*.coffee"
  },
  {
    "path": "example/dashboard-app/.editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\n\nroot = true\n\n\n[*]\n\n# Change these settings to your own preference\nindent_style = space\nindent_size = 2\n\n# We recommend you to keep these unchanged\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": "example/dashboard-app/.gitattributes",
    "content": "* text=auto"
  },
  {
    "path": "example/dashboard-app/.gitignore",
    "content": "node_modules\npublic\n.tmp\n.idea\nclient/bower_components\ndist\n/server/config/local.env.js\nstormpath.yml\n"
  },
  {
    "path": "example/dashboard-app/.travis.yml",
    "content": "language: node_js\nnode_js:\n  - '0.10'\n  - '0.11'\nbefore_script:\n  - npm install -g bower grunt-cli\n  - bower install\nservices: mongodb"
  },
  {
    "path": "example/dashboard-app/.yo-rc.json",
    "content": "{\n  \"generator-angular-fullstack\": {\n    \"insertRoutes\": true,\n    \"registerRoutesFile\": \"server/routes.js\",\n    \"routesNeedle\": \"// Insert routes below\",\n    \"routesBase\": \"/api/\",\n    \"pluralizeRoutes\": true,\n    \"insertSockets\": true,\n    \"registerSocketsFile\": \"server/config/socketio.js\",\n    \"socketsNeedle\": \"// Insert sockets below\",\n    \"filters\": {\n      \"js\": true,\n      \"html\": true,\n      \"css\": true,\n      \"uirouter\": true,\n      \"bootstrap\": true,\n      \"uibootstrap\": false\n    }\n  },\n  \"generator-ng-component\": {\n    \"routeDirectory\": \"client/app/\",\n    \"directiveDirectory\": \"client/app/\",\n    \"filterDirectory\": \"client/app/\",\n    \"serviceDirectory\": \"client/app/\",\n    \"basePath\": \"client\",\n    \"moduleName\": \"\",\n    \"filters\": [\n      \"uirouter\"\n    ],\n    \"extensions\": [\n      \"js\",\n      \"html\",\n      \"css\"\n    ],\n    \"directiveSimpleTemplates\": \"\",\n    \"directiveComplexTemplates\": \"\",\n    \"filterTemplates\": \"\",\n    \"serviceTemplates\": \"\",\n    \"factoryTemplates\": \"\",\n    \"controllerTemplates\": \"\",\n    \"decoratorTemplates\": \"\",\n    \"providerTemplates\": \"\",\n    \"routeTemplates\": \"\"\n  }\n}"
  },
  {
    "path": "example/dashboard-app/Gruntfile.js",
    "content": "// Generated on 2015-09-24 using generator-angular-fullstack 2.0.13\n'use strict';\n\nmodule.exports = function (grunt) {\n  var localConfig;\n  try {\n    localConfig = require('./server/config/local.env');\n  } catch(e) {\n    localConfig = {};\n  }\n\n  // Load grunt tasks automatically, when needed\n  require('jit-grunt')(grunt, {\n    express: 'grunt-express-server',\n    useminPrepare: 'grunt-usemin',\n    ngtemplates: 'grunt-angular-templates',\n    cdnify: 'grunt-google-cdn',\n    protractor: 'grunt-protractor-runner',\n    injector: 'grunt-asset-injector',\n    buildcontrol: 'grunt-build-control'\n  });\n\n  // Time how long tasks take. Can help when optimizing build times\n  require('time-grunt')(grunt);\n\n  // Define the configuration for all the tasks\n  grunt.initConfig({\n\n    // Project settings\n    pkg: grunt.file.readJSON('package.json'),\n    yeoman: {\n      // configurable paths\n      client: require('./bower.json').appPath || 'client',\n      dist: 'dist'\n    },\n    express: {\n      options: {\n        port: process.env.PORT || 9000,\n        // output option will force Grunt to wait for this\n        // line to be seen in server output, before continuing\n        output: 'Stormpath Ready'\n      },\n      dev: {\n        options: {\n          script: 'server/app.js',\n          debug: true\n        }\n      },\n      prod: {\n        options: {\n          script: 'dist/server/app.js'\n        }\n      }\n    },\n    open: {\n      server: {\n        url: 'http://localhost:<%= express.options.port %>'\n      }\n    },\n    watch: {\n      injectJS: {\n        files: [\n          '<%= yeoman.client %>/{app,components}/**/*.js',\n          '!<%= yeoman.client %>/{app,components}/**/*.spec.js',\n          '!<%= yeoman.client %>/{app,components}/**/*.mock.js',\n          '!<%= yeoman.client %>/app/app.js'],\n        tasks: ['injector:scripts']\n      },\n      injectCss: {\n        files: [\n          '<%= yeoman.client %>/{app,components}/**/*.css'\n        ],\n        tasks: ['injector:css']\n      },\n      mochaTest: {\n        files: ['server/**/*.spec.js'],\n        tasks: ['env:test', 'mochaTest']\n      },\n      jsTest: {\n        files: [\n          '<%= yeoman.client %>/{app,components}/**/*.spec.js',\n          '<%= yeoman.client %>/{app,components}/**/*.mock.js'\n        ],\n        tasks: ['newer:jshint:all', 'karma']\n      },\n      gruntfile: {\n        files: ['Gruntfile.js']\n      },\n      livereload: {\n        files: [\n          '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.css',\n          '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.html',\n          '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',\n          '!{.tmp,<%= yeoman.client %>}{app,components}/**/*.spec.js',\n          '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js',\n          '<%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}'\n        ],\n        options: {\n          livereload: true\n        }\n      },\n      express: {\n        files: [\n          'server/**/*.{js,json}'\n        ],\n        tasks: ['express:dev', 'wait'],\n        options: {\n          livereload: true,\n          nospawn: true //Without this option specified express won't be reloaded\n        }\n      }\n    },\n\n    // Make sure code styles are up to par and there are no obvious mistakes\n    jshint: {\n      options: {\n        jshintrc: '<%= yeoman.client %>/.jshintrc',\n        reporter: require('jshint-stylish')\n      },\n      server: {\n        options: {\n          jshintrc: 'server/.jshintrc'\n        },\n        src: [\n          'server/**/*.js',\n          '!server/**/*.spec.js'\n        ]\n      },\n      serverTest: {\n        options: {\n          jshintrc: 'server/.jshintrc-spec'\n        },\n        src: ['server/**/*.spec.js']\n      },\n      all: [\n        '<%= yeoman.client %>/{app,components}/**/*.js',\n        '!<%= yeoman.client %>/{app,components}/**/*.spec.js',\n        '!<%= yeoman.client %>/{app,components}/**/*.mock.js'\n      ],\n      test: {\n        src: [\n          '<%= yeoman.client %>/{app,components}/**/*.spec.js',\n          '<%= yeoman.client %>/{app,components}/**/*.mock.js'\n        ]\n      }\n    },\n\n    // Empties folders to start fresh\n    clean: {\n      dist: {\n        files: [{\n          dot: true,\n          src: [\n            '.tmp',\n            '<%= yeoman.dist %>/*',\n            '!<%= yeoman.dist %>/.git*',\n            '!<%= yeoman.dist %>/.openshift',\n            '!<%= yeoman.dist %>/Procfile'\n          ]\n        }]\n      },\n      server: '.tmp'\n    },\n\n    // Add vendor prefixed styles\n    autoprefixer: {\n      options: {\n        browsers: ['last 1 version']\n      },\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '.tmp/',\n          src: '{,*/}*.css',\n          dest: '.tmp/'\n        }]\n      }\n    },\n\n    // Debugging with node inspector\n    'node-inspector': {\n      custom: {\n        options: {\n          'web-host': 'localhost'\n        }\n      }\n    },\n\n    // Use nodemon to run server in debug mode with an initial breakpoint\n    nodemon: {\n      debug: {\n        script: 'server/app.js',\n        options: {\n          nodeArgs: ['--debug-brk'],\n          env: {\n            PORT: process.env.PORT || 9000\n          },\n          callback: function (nodemon) {\n            nodemon.on('log', function (event) {\n              console.log(event.colour);\n            });\n\n            // opens browser on initial server start\n            nodemon.on('config:update', function () {\n              setTimeout(function () {\n                require('open')('http://localhost:8080/debug?port=5858');\n              }, 500);\n            });\n          }\n        }\n      }\n    },\n\n    // Automatically inject Bower components into the app\n    wiredep: {\n      target: {\n        src: '<%= yeoman.client %>/index.html',\n        ignorePath: '<%= yeoman.client %>/',\n        exclude: [/bootstrap-sass-official/, /bootstrap.js/, '/json3/', '/es5-shim/']\n      }\n    },\n\n    // Renames files for browser caching purposes\n    rev: {\n      dist: {\n        files: {\n          src: [\n            '<%= yeoman.dist %>/public/{,*/}*.js',\n            '<%= yeoman.dist %>/public/{,*/}*.css',\n            '<%= yeoman.dist %>/public/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',\n            '<%= yeoman.dist %>/public/assets/fonts/*'\n          ]\n        }\n      }\n    },\n\n    // Reads HTML for usemin blocks to enable smart builds that automatically\n    // concat, minify and revision files. Creates configurations in memory so\n    // additional tasks can operate on them\n    useminPrepare: {\n      html: ['<%= yeoman.client %>/index.html'],\n      options: {\n        dest: '<%= yeoman.dist %>/public'\n      }\n    },\n\n    // Performs rewrites based on rev and the useminPrepare configuration\n    usemin: {\n      html: ['<%= yeoman.dist %>/public/{,*/}*.html'],\n      css: ['<%= yeoman.dist %>/public/{,*/}*.css'],\n      js: ['<%= yeoman.dist %>/public/{,*/}*.js'],\n      options: {\n        assetsDirs: [\n          '<%= yeoman.dist %>/public',\n          '<%= yeoman.dist %>/public/assets/images'\n        ],\n        // This is so we update image references in our ng-templates\n        patterns: {\n          js: [\n            [/(assets\\/images\\/.*?\\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']\n          ]\n        }\n      }\n    },\n\n    // The following *-min tasks produce minified files in the dist folder\n    imagemin: {\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '<%= yeoman.client %>/assets/images',\n          src: '{,*/}*.{png,jpg,jpeg,gif}',\n          dest: '<%= yeoman.dist %>/public/assets/images'\n        }]\n      }\n    },\n\n    svgmin: {\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '<%= yeoman.client %>/assets/images',\n          src: '{,*/}*.svg',\n          dest: '<%= yeoman.dist %>/public/assets/images'\n        }]\n      }\n    },\n\n    // Allow the use of non-minsafe AngularJS files. Automatically makes it\n    // minsafe compatible so Uglify does not destroy the ng references\n    ngAnnotate: {\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '.tmp/concat',\n          src: '*/**.js',\n          dest: '.tmp/concat'\n        }]\n      }\n    },\n\n    // Package all the html partials into a single javascript payload\n    ngtemplates: {\n      options: {\n        // This should be the name of your apps angular module\n        module: 'dashboardApp',\n        htmlmin: {\n          collapseBooleanAttributes: true,\n          collapseWhitespace: true,\n          removeAttributeQuotes: true,\n          removeEmptyAttributes: true,\n          removeRedundantAttributes: true,\n          removeScriptTypeAttributes: true,\n          removeStyleLinkTypeAttributes: true\n        },\n        usemin: 'app/app.js'\n      },\n      main: {\n        cwd: '<%= yeoman.client %>',\n        src: ['{app,components}/**/*.html'],\n        dest: '.tmp/templates.js'\n      },\n      tmp: {\n        cwd: '.tmp',\n        src: ['{app,components}/**/*.html'],\n        dest: '.tmp/tmp-templates.js'\n      }\n    },\n\n    // Replace Google CDN references\n    cdnify: {\n      dist: {\n        html: ['<%= yeoman.dist %>/public/*.html']\n      }\n    },\n\n    // Copies remaining files to places other tasks can use\n    copy: {\n      dist: {\n        files: [{\n          expand: true,\n          dot: true,\n          cwd: '<%= yeoman.client %>',\n          dest: '<%= yeoman.dist %>/public',\n          src: [\n            '*.{ico,png,txt}',\n            '.htaccess',\n            'bower_components/**/*',\n            'assets/images/{,*/}*.{webp}',\n            'assets/fonts/**/*',\n            'index.html'\n          ]\n        }, {\n          expand: true,\n          cwd: '.tmp/images',\n          dest: '<%= yeoman.dist %>/public/assets/images',\n          src: ['generated/*']\n        }, {\n          expand: true,\n          dest: '<%= yeoman.dist %>',\n          src: [\n            'package.json',\n            'server/**/*'\n          ]\n        }]\n      },\n      styles: {\n        expand: true,\n        cwd: '<%= yeoman.client %>',\n        dest: '.tmp/',\n        src: ['{app,components}/**/*.css']\n      }\n    },\n\n    buildcontrol: {\n      options: {\n        dir: 'dist',\n        commit: true,\n        push: true,\n        connectCommits: false,\n        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'\n      },\n      heroku: {\n        options: {\n          remote: 'heroku',\n          branch: 'master'\n        }\n      },\n      openshift: {\n        options: {\n          remote: 'openshift',\n          branch: 'master'\n        }\n      }\n    },\n\n    // Run some tasks in parallel to speed up the build process\n    concurrent: {\n      server: [\n      ],\n      test: [\n      ],\n      debug: {\n        tasks: [\n          'nodemon',\n          'node-inspector'\n        ],\n        options: {\n          logConcurrentOutput: true\n        }\n      },\n      dist: [\n        'imagemin',\n        'svgmin'\n      ]\n    },\n\n    // Test settings\n    karma: {\n      unit: {\n        configFile: 'karma.conf.js',\n        singleRun: true\n      }\n    },\n\n    mochaTest: {\n      options: {\n        reporter: 'spec'\n      },\n      src: ['server/**/*.spec.js']\n    },\n\n    protractor: {\n      options: {\n        configFile: 'protractor.conf.js'\n      },\n      chrome: {\n        options: {\n          args: {\n            browser: 'chrome'\n          }\n        }\n      }\n    },\n\n    env: {\n      test: {\n        NODE_ENV: 'test'\n      },\n      prod: {\n        NODE_ENV: 'production'\n      },\n      all: localConfig\n    },\n\n    injector: {\n      options: {\n\n      },\n      // Inject application script files into index.html (doesn't include bower)\n      scripts: {\n        options: {\n          transform: function(filePath) {\n            filePath = filePath.replace('/client/', '');\n            filePath = filePath.replace('/.tmp/', '');\n            return '<script src=\"' + filePath + '\"></script>';\n          },\n          starttag: '<!-- injector:js -->',\n          endtag: '<!-- endinjector -->'\n        },\n        files: {\n          '<%= yeoman.client %>/index.html': [\n              ['{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',\n               '!{.tmp,<%= yeoman.client %>}/app/app.js',\n               '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.spec.js',\n               '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js']\n            ]\n        }\n      },\n\n      // Inject component css into index.html\n      css: {\n        options: {\n          transform: function(filePath) {\n            filePath = filePath.replace('/client/', '');\n            filePath = filePath.replace('/.tmp/', '');\n            return '<link rel=\"stylesheet\" href=\"' + filePath + '\">';\n          },\n          starttag: '<!-- injector:css -->',\n          endtag: '<!-- endinjector -->'\n        },\n        files: {\n          '<%= yeoman.client %>/index.html': [\n            '<%= yeoman.client %>/{app,components}/**/*.css'\n          ]\n        }\n      }\n    },\n  });\n\n  // Used for delaying livereload until after server has restarted\n  grunt.registerTask('wait', function () {\n    grunt.log.ok('Waiting for server reload...');\n\n    var done = this.async();\n\n    setTimeout(function () {\n      grunt.log.writeln('Done waiting!');\n      done();\n    }, 1500);\n  });\n\n  grunt.registerTask('express-keepalive', 'Keep grunt running', function() {\n    this.async();\n  });\n\n  grunt.registerTask('serve', function (target) {\n    if (target === 'dist') {\n      return grunt.task.run(['build', 'env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']);\n    }\n\n    if (target === 'debug') {\n      return grunt.task.run([\n        'clean:server',\n        'env:all',\n        'concurrent:server',\n        'injector',\n        'wiredep',\n        'autoprefixer',\n        'concurrent:debug'\n      ]);\n    }\n\n    grunt.task.run([\n      'clean:server',\n      'env:all',\n      'concurrent:server',\n      'injector',\n      'wiredep',\n      'autoprefixer',\n      'express:dev',\n      'wait',\n      'open',\n      'watch'\n    ]);\n  });\n\n  grunt.registerTask('server', function () {\n    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');\n    grunt.task.run(['serve']);\n  });\n\n  grunt.registerTask('test', function(target) {\n    if (target === 'server') {\n      return grunt.task.run([\n        'env:all',\n        'env:test',\n        'mochaTest'\n      ]);\n    }\n\n    else if (target === 'client') {\n      return grunt.task.run([\n        'clean:server',\n        'env:all',\n        'concurrent:test',\n        'injector',\n        'autoprefixer',\n        'karma'\n      ]);\n    }\n\n    else if (target === 'e2e') {\n      return grunt.task.run([\n        'clean:server',\n        'env:all',\n        'env:test',\n        'concurrent:test',\n        'injector',\n        'wiredep',\n        'autoprefixer',\n        'express:dev',\n        'protractor'\n      ]);\n    }\n\n    else grunt.task.run([\n      'test:server',\n      'test:client'\n    ]);\n  });\n\n  grunt.registerTask('build', [\n    'clean:dist',\n    'concurrent:dist',\n    'injector',\n    'wiredep',\n    'useminPrepare',\n    'autoprefixer',\n    'ngtemplates',\n    'concat',\n    'ngAnnotate',\n    'copy:dist',\n    'cdnify',\n    'cssmin',\n    'uglify',\n    'rev',\n    'usemin'\n  ]);\n\n  grunt.registerTask('default', [\n    'newer:jshint',\n    'test',\n    'build'\n  ]);\n};\n"
  },
  {
    "path": "example/dashboard-app/README.md",
    "content": "# Stormpath Angular SDK Example\n\nThis folder contains an example application that is built with the [Stormpath Angular SDK][]\nand [Stormpath Express][].\n\nThis application is the same one that is built when you follow the [Yeoman Guide][].\n\n#### Running the Example Application\n\n1. To run this application, you will need Bower and Grunt as global packages:\n\n  ```bash\n  npm install -g grunt bower\n  ```\n\n2. Clone this repo to your computer, and enter the directory for this example:\n\n  ```bash\n  git clone https://github.com/stormpath/stormpath-sdk-angularjs.git\n  cd stormpath-sdk-angularjs/example/dashboard-app\n  ```\n\n3. Install the dependencies:\n\n  ```bash\n  npm install\n  bower install\n  ```\n4. Export your environment variables for your Stormpath Tenant and Application:\n\n  ```bash\n  export STORMPATH_CLIENT_APIKEY_ID=xxx\n  export STORMPATH_CLIENT_APIKEY_SECRET=xxx\n  export STORMPATH_APPLICATION_HREF=xxx\n  ```\n\n5. Start the server with Grunt, this should start the server and open the Angular\n  application in your browser:\n\n  ```bash\n  grunt serve\n  ```\n\n[Stormpath Angular SDK]: https://github.com/stormpath/stormpath-sdk-angularjs\n[Stormpath Express]: https://github.com/stormpath/stormpath-express\n[Yeoman Guide]: https://docs.stormpath.com/angularjs/guide\n"
  },
  {
    "path": "example/dashboard-app/bower.json",
    "content": "{\n  \"name\": \"dashboard\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"angular\": \">=1.2.*\",\n    \"json3\": \"~3.3.1\",\n    \"es5-shim\": \"~3.0.1\",\n    \"jquery\": \"~1.11.0\",\n    \"bootstrap\": \"~3.1.1\",\n    \"angular-resource\": \">=1.2.*\",\n    \"angular-cookies\": \">=1.2.*\",\n    \"angular-sanitize\": \">=1.2.*\",\n    \"font-awesome\": \">=4.1.0\",\n    \"lodash\": \"~2.4.1\",\n    \"angular-ui-router\": \"~0.2.10\",\n    \"stormpath-sdk-angularjs\": \"~1.0.0\"\n  },\n  \"devDependencies\": {\n    \"angular-mocks\": \">=1.2.*\",\n    \"angular-scenario\": \">=1.2.*\"\n  }\n}\n"
  },
  {
    "path": "example/dashboard-app/client/.htaccess",
    "content": "# Apache Configuration File\n\n# (!) Using `.htaccess` files slows down Apache, therefore, if you have access\n# to the main server config file (usually called `httpd.conf`), you should add\n# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.\n\n# ##############################################################################\n# # CROSS-ORIGIN RESOURCE SHARING (CORS)                                       #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Cross-domain AJAX requests                                                 |\n# ------------------------------------------------------------------------------\n\n# Enable cross-origin AJAX requests.\n# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity\n# http://enable-cors.org/\n\n# <IfModule mod_headers.c>\n#    Header set Access-Control-Allow-Origin \"*\"\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | CORS-enabled images                                                        |\n# ------------------------------------------------------------------------------\n\n# Send the CORS header for images when browsers request it.\n# https://developer.mozilla.org/en/CORS_Enabled_Image\n# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html\n# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/\n\n<IfModule mod_setenvif.c>\n    <IfModule mod_headers.c>\n        <FilesMatch \"\\.(gif|ico|jpe?g|png|svg|svgz|webp)$\">\n            SetEnvIf Origin \":\" IS_CORS\n            Header set Access-Control-Allow-Origin \"*\" env=IS_CORS\n        </FilesMatch>\n    </IfModule>\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Web fonts access                                                           |\n# ------------------------------------------------------------------------------\n\n# Allow access from all domains for web fonts\n\n<IfModule mod_headers.c>\n    <FilesMatch \"\\.(eot|font.css|otf|ttc|ttf|woff)$\">\n        Header set Access-Control-Allow-Origin \"*\"\n    </FilesMatch>\n</IfModule>\n\n\n# ##############################################################################\n# # ERRORS                                                                     #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | 404 error prevention for non-existing redirected folders                   |\n# ------------------------------------------------------------------------------\n\n# Prevent Apache from returning a 404 error for a rewrite if a directory\n# with the same name does not exist.\n# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews\n# http://www.webmasterworld.com/apache/3808792.htm\n\nOptions -MultiViews\n\n# ------------------------------------------------------------------------------\n# | Custom error messages / pages                                              |\n# ------------------------------------------------------------------------------\n\n# You can customize what Apache returns to the client in case of an error (see\n# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:\n\nErrorDocument 404 /404.html\n\n\n# ##############################################################################\n# # INTERNET EXPLORER                                                          #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Better website experience                                                  |\n# ------------------------------------------------------------------------------\n\n# Force IE to render pages in the highest available mode in the various\n# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.\n\n<IfModule mod_headers.c>\n    Header set X-UA-Compatible \"IE=edge\"\n    # `mod_headers` can't match based on the content-type, however, we only\n    # want to send this header for HTML pages and not for the other resources\n    <FilesMatch \"\\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$\">\n        Header unset X-UA-Compatible\n    </FilesMatch>\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Cookie setting from iframes                                                |\n# ------------------------------------------------------------------------------\n\n# Allow cookies to be set from iframes in IE.\n\n# <IfModule mod_headers.c>\n#   Header set P3P \"policyref=\\\"/w3c/p3p.xml\\\", CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"\"\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | Screen flicker                                                             |\n# ------------------------------------------------------------------------------\n\n# Stop screen flicker in IE on CSS rollovers (this only works in\n# combination with the `ExpiresByType` directives for images from below).\n\n# BrowserMatch \"MSIE\" brokenvary=1\n# BrowserMatch \"Mozilla/4.[0-9]{2}\" brokenvary=1\n# BrowserMatch \"Opera\" !brokenvary\n# SetEnvIf brokenvary 1 force-no-vary\n\n\n# ##############################################################################\n# # MIME TYPES AND ENCODING                                                    #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Proper MIME types for all files                                            |\n# ------------------------------------------------------------------------------\n\n<IfModule mod_mime.c>\n\n  # Audio\n    AddType audio/mp4                                   m4a f4a f4b\n    AddType audio/ogg                                   oga ogg\n\n  # JavaScript\n    # Normalize to standard type (it's sniffed in IE anyways):\n    # http://tools.ietf.org/html/rfc4329#section-7.2\n    AddType application/javascript                      js jsonp\n    AddType application/json                            json\n\n  # Video\n    AddType video/mp4                                   mp4 m4v f4v f4p\n    AddType video/ogg                                   ogv\n    AddType video/webm                                  webm\n    AddType video/x-flv                                 flv\n\n  # Web fonts\n    AddType application/font-woff                       woff\n    AddType application/vnd.ms-fontobject               eot\n\n    # Browsers usually ignore the font MIME types and sniff the content,\n    # however, Chrome shows a warning if other MIME types are used for the\n    # following fonts.\n    AddType application/x-font-ttf                      ttc ttf\n    AddType font/opentype                               otf\n\n    # Make SVGZ fonts work on iPad:\n    # https://twitter.com/FontSquirrel/status/14855840545\n    AddType     image/svg+xml                           svg svgz\n    AddEncoding gzip                                    svgz\n\n  # Other\n    AddType application/octet-stream                    safariextz\n    AddType application/x-chrome-extension              crx\n    AddType application/x-opera-extension               oex\n    AddType application/x-shockwave-flash               swf\n    AddType application/x-web-app-manifest+json         webapp\n    AddType application/x-xpinstall                     xpi\n    AddType application/xml                             atom rdf rss xml\n    AddType image/webp                                  webp\n    AddType image/x-icon                                ico\n    AddType text/cache-manifest                         appcache manifest\n    AddType text/vtt                                    vtt\n    AddType text/x-component                            htc\n    AddType text/x-vcard                                vcf\n\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | UTF-8 encoding                                                             |\n# ------------------------------------------------------------------------------\n\n# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.\nAddDefaultCharset utf-8\n\n# Force UTF-8 for certain file formats.\n<IfModule mod_mime.c>\n    AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml\n</IfModule>\n\n\n# ##############################################################################\n# # URL REWRITES                                                               #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Rewrite engine                                                             |\n# ------------------------------------------------------------------------------\n\n# Turning on the rewrite engine and enabling the `FollowSymLinks` option is\n# necessary for the following directives to work.\n\n# If your web host doesn't allow the `FollowSymlinks` option, you may need to\n# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the\n# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks\n\n# Also, some cloud hosting services require `RewriteBase` to be set:\n# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site\n\n<IfModule mod_rewrite.c>\n    Options +FollowSymlinks\n  # Options +SymLinksIfOwnerMatch\n    RewriteEngine On\n  # RewriteBase /\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Suppressing / Forcing the \"www.\" at the beginning of URLs                  |\n# ------------------------------------------------------------------------------\n\n# The same content should never be available under two different URLs especially\n# not with and without \"www.\" at the beginning. This can cause SEO problems\n# (duplicate content), therefore, you should choose one of the alternatives and\n# redirect the other one.\n\n# By default option 1 (no \"www.\") is activated:\n# http://no-www.org/faq.php?q=class_b\n\n# If you'd prefer to use option 2, just comment out all the lines from option 1\n# and uncomment the ones from option 2.\n\n# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Option 1: rewrite www.example.com → example.com\n\n<IfModule mod_rewrite.c>\n    RewriteCond %{HTTPS} !=on\n    RewriteCond %{HTTP_HOST} ^www\\.(.+)$ [NC]\n    RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]\n</IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Option 2: rewrite example.com → www.example.com\n\n# Be aware that the following might not be a good idea if you use \"real\"\n# subdomains for certain parts of your website.\n\n# <IfModule mod_rewrite.c>\n#    RewriteCond %{HTTPS} !=on\n#    RewriteCond %{HTTP_HOST} !^www\\..+$ [NC]\n#    RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n\n# ##############################################################################\n# # SECURITY                                                                   #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Content Security Policy (CSP)                                              |\n# ------------------------------------------------------------------------------\n\n# You can mitigate the risk of cross-site scripting and other content-injection\n# attacks by setting a Content Security Policy which whitelists trusted sources\n# of content for your site.\n\n# The example header below allows ONLY scripts that are loaded from the current\n# site's origin (no inline scripts, no CDN, etc). This almost certainly won't\n# work as-is for your site!\n\n# To get all the details you'll need to craft a reasonable policy for your site,\n# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or\n# see the specification: http://w3.org/TR/CSP).\n\n# <IfModule mod_headers.c>\n#    Header set Content-Security-Policy \"script-src 'self'; object-src 'self'\"\n#    <FilesMatch \"\\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$\">\n#        Header unset Content-Security-Policy\n#    </FilesMatch>\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | File access                                                                |\n# ------------------------------------------------------------------------------\n\n# Block access to directories without a default document.\n# Usually you should leave this uncommented because you shouldn't allow anyone\n# to surf through every directory on your server (which may includes rather\n# private places like the CMS's directories).\n\n<IfModule mod_autoindex.c>\n    Options -Indexes\n</IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Block access to hidden files and directories.\n# This includes directories used by version control systems such as Git and SVN.\n\n<IfModule mod_rewrite.c>\n    RewriteCond %{SCRIPT_FILENAME} -d [OR]\n    RewriteCond %{SCRIPT_FILENAME} -f\n    RewriteRule \"(^|/)\\.\" - [F]\n</IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Block access to backup and source files.\n# These files may be left by some text editors and can pose a great security\n# danger when anyone has access to them.\n\n<FilesMatch \"(^#.*#|\\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$\">\n    Order allow,deny\n    Deny from all\n    Satisfy All\n</FilesMatch>\n\n# ------------------------------------------------------------------------------\n# | Secure Sockets Layer (SSL)                                                 |\n# ------------------------------------------------------------------------------\n\n# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:\n# prevent `https://www.example.com` when your certificate only allows\n# `https://secure.example.com`.\n\n# <IfModule mod_rewrite.c>\n#    RewriteCond %{SERVER_PORT} !^443\n#    RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Force client-side SSL redirection.\n\n# If a user types \"example.com\" in his browser, the above rule will redirect him\n# to the secure version of the site. That still leaves a window of opportunity\n# (the initial HTTP connection) for an attacker to downgrade or redirect the\n# request. The following header ensures that browser will ONLY connect to your\n# server via HTTPS, regardless of what the users type in the address bar.\n# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/\n\n# <IfModule mod_headers.c>\n#    Header set Strict-Transport-Security max-age=16070400;\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | Server software information                                                |\n# ------------------------------------------------------------------------------\n\n# Avoid displaying the exact Apache version number, the description of the\n# generic OS-type and the information about Apache's compiled-in modules.\n\n# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!\n\n# ServerTokens Prod\n\n\n# ##############################################################################\n# # WEB PERFORMANCE                                                            #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Compression                                                                |\n# ------------------------------------------------------------------------------\n\n<IfModule mod_deflate.c>\n\n    # Force compression for mangled headers.\n    # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping\n    <IfModule mod_setenvif.c>\n        <IfModule mod_headers.c>\n            SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\\s*,?\\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding\n            RequestHeader append Accept-Encoding \"gzip,deflate\" env=HAVE_Accept-Encoding\n        </IfModule>\n    </IfModule>\n\n    # Compress all output labeled with one of the following MIME-types\n    # (for Apache versions below 2.3.7, you don't need to enable `mod_filter`\n    #  and can remove the `<IfModule mod_filter.c>` and `</IfModule>` lines\n    #  as `AddOutputFilterByType` is still in the core directives).\n    <IfModule mod_filter.c>\n        AddOutputFilterByType DEFLATE application/atom+xml \\\n                                      application/javascript \\\n                                      application/json \\\n                                      application/rss+xml \\\n                                      application/vnd.ms-fontobject \\\n                                      application/x-font-ttf \\\n                                      application/x-web-app-manifest+json \\\n                                      application/xhtml+xml \\\n                                      application/xml \\\n                                      font/opentype \\\n                                      image/svg+xml \\\n                                      image/x-icon \\\n                                      text/css \\\n                                      text/html \\\n                                      text/plain \\\n                                      text/x-component \\\n                                      text/xml\n    </IfModule>\n\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Content transformations                                                    |\n# ------------------------------------------------------------------------------\n\n# Prevent some of the mobile network providers from modifying the content of\n# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.\n\n# <IfModule mod_headers.c>\n#    Header set Cache-Control \"no-transform\"\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | ETag removal                                                               |\n# ------------------------------------------------------------------------------\n\n# Since we're sending far-future expires headers (see below), ETags can\n# be removed: http://developer.yahoo.com/performance/rules.html#etags.\n\n# `FileETag None` is not enough for every server.\n<IfModule mod_headers.c>\n    Header unset ETag\n</IfModule>\n\nFileETag None\n\n# ------------------------------------------------------------------------------\n# | Expires headers (for better cache control)                                 |\n# ------------------------------------------------------------------------------\n\n# The following expires headers are set pretty far in the future. If you don't\n# control versioning with filename-based cache busting, consider lowering the\n# cache time for resources like CSS and JS to something like 1 week.\n\n<IfModule mod_expires.c>\n\n    ExpiresActive on\n    ExpiresDefault                                      \"access plus 1 month\"\n\n  # CSS\n    ExpiresByType text/css                              \"access plus 1 year\"\n\n  # Data interchange\n    ExpiresByType application/json                      \"access plus 0 seconds\"\n    ExpiresByType application/xml                       \"access plus 0 seconds\"\n    ExpiresByType text/xml                              \"access plus 0 seconds\"\n\n  # Favicon (cannot be renamed!)\n    ExpiresByType image/x-icon                          \"access plus 1 week\"\n\n  # HTML components (HTCs)\n    ExpiresByType text/x-component                      \"access plus 1 month\"\n\n  # HTML\n    ExpiresByType text/html                             \"access plus 0 seconds\"\n\n  # JavaScript\n    ExpiresByType application/javascript                \"access plus 1 year\"\n\n  # Manifest files\n    ExpiresByType application/x-web-app-manifest+json   \"access plus 0 seconds\"\n    ExpiresByType text/cache-manifest                   \"access plus 0 seconds\"\n\n  # Media\n    ExpiresByType audio/ogg                             \"access plus 1 month\"\n    ExpiresByType image/gif                             \"access plus 1 month\"\n    ExpiresByType image/jpeg                            \"access plus 1 month\"\n    ExpiresByType image/png                             \"access plus 1 month\"\n    ExpiresByType video/mp4                             \"access plus 1 month\"\n    ExpiresByType video/ogg                             \"access plus 1 month\"\n    ExpiresByType video/webm                            \"access plus 1 month\"\n\n  # Web feeds\n    ExpiresByType application/atom+xml                  \"access plus 1 hour\"\n    ExpiresByType application/rss+xml                   \"access plus 1 hour\"\n\n  # Web fonts\n    ExpiresByType application/font-woff                 \"access plus 1 month\"\n    ExpiresByType application/vnd.ms-fontobject         \"access plus 1 month\"\n    ExpiresByType application/x-font-ttf                \"access plus 1 month\"\n    ExpiresByType font/opentype                         \"access plus 1 month\"\n    ExpiresByType image/svg+xml                         \"access plus 1 month\"\n\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Filename-based cache busting                                               |\n# ------------------------------------------------------------------------------\n\n# If you're not using a build process to manage your filename version revving,\n# you might want to consider enabling the following directives to route all\n# requests such as `/css/style.12345.css` to `/css/style.css`.\n\n# To understand why this is important and a better idea than `*.css?v231`, read:\n# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring\n\n# <IfModule mod_rewrite.c>\n#    RewriteCond %{REQUEST_FILENAME} !-f\n#    RewriteCond %{REQUEST_FILENAME} !-d\n#    RewriteRule ^(.+)\\.(\\d+)\\.(js|css|png|jpg|gif)$ $1.$3 [L]\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | File concatenation                                                         |\n# ------------------------------------------------------------------------------\n\n# Allow concatenation from within specific CSS and JS files, e.g.:\n# Inside of `script.combined.js` you could have\n#   <!--#include file=\"libs/jquery.js\" -->\n#   <!--#include file=\"plugins/jquery.idletimer.js\" -->\n# and they would be included into this single file.\n\n# <IfModule mod_include.c>\n#    <FilesMatch \"\\.combined\\.js$\">\n#        Options +Includes\n#        AddOutputFilterByType INCLUDES application/javascript application/json\n#        SetOutputFilter INCLUDES\n#    </FilesMatch>\n#    <FilesMatch \"\\.combined\\.css$\">\n#        Options +Includes\n#        AddOutputFilterByType INCLUDES text/css\n#        SetOutputFilter INCLUDES\n#    </FilesMatch>\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | Persistent connections                                                     |\n# ------------------------------------------------------------------------------\n\n# Allow multiple requests to be sent over the same TCP connection:\n# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.\n\n# Enable if you serve a lot of static content but, be aware of the\n# possible disadvantages!\n\n# <IfModule mod_headers.c>\n#    Header set Connection Keep-Alive\n# </IfModule>\n"
  },
  {
    "path": "example/dashboard-app/client/.jshintrc",
    "content": "{\n  \"node\": true,\n  \"browser\": true,\n  \"esnext\": true,\n  \"bitwise\": true,\n  \"camelcase\": true,\n  \"curly\": true,\n  \"eqeqeq\": true,\n  \"immed\": true,\n  \"indent\": 2,\n  \"latedef\": true,\n  \"newcap\": true,\n  \"noarg\": true,\n  \"quotmark\": \"single\",\n  \"regexp\": true,\n  \"undef\": true,\n  \"unused\": true,\n  \"strict\": true,\n  \"trailing\": true,\n  \"smarttabs\": true,\n  \"globals\": {\n    \"jQuery\": true,\n    \"angular\": true,\n    \"console\": true,\n    \"$\": true,\n    \"_\": true,\n    \"moment\": true,\n    \"describe\": true,\n    \"beforeEach\": true,\n    \"module\": true,\n    \"inject\": true,\n    \"it\": true,\n    \"expect\": true,\n    \"browser\": true,\n    \"element\": true,\n    \"by\": true\n  }\n}\n"
  },
  {
    "path": "example/dashboard-app/client/app/app.css",
    "content": "\n/**\n * Bootstrap Fonts\n */\n\n@font-face {\n    font-family: 'Glyphicons Halflings';\n    src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot');\n    src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),\n    url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'),\n    url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'),\n    url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n\n/**\n *Font Awesome Fonts\n */\n\n@font-face {\n    font-family: 'FontAwesome';\n    src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?v=4.1.0');\n    src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),\n    url('../bower_components/font-awesome/fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),\n    url('../bower_components/font-awesome/fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),\n    url('../bower_components/font-awesome/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n/**\n * App-wide Styles\n */\n\n.browsehappy {\n    margin: 0.2em 0;\n    background: #ccc;\n    color: #000;\n    padding: 0.2em 0;\n}\n"
  },
  {
    "path": "example/dashboard-app/client/app/app.js",
    "content": "'use strict';\n\nangular.module('dashboardApp', [\n  'ngCookies',\n  'ngResource',\n  'ngSanitize',\n  'ui.router',\n  'stormpath',\n  'stormpath.templates'\n])\n  .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {\n    $urlRouterProvider\n      .otherwise('/');\n\n    $locationProvider.html5Mode(true);\n  })\n  .run(function($stormpath,$rootScope,$state){\n\n    /*\n      In this example we use UI router, and this\n      is how we tell the Stormpath module which\n      states we would like to use to use for login\n      and post-login\n     */\n\n    $stormpath.uiRouter({\n      loginState: 'login',\n      defaultPostLoginState: 'main'\n    });\n\n    /*\n      We want to redirect users back to the login\n      state after they logout, so we watch for the\n      logout event and then transition them to the\n      login state\n     */\n    $rootScope.$on('$sessionEnd',function () {\n      $state.transitionTo('login');\n    });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/forgot/forgot.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('ForgotCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/forgot/forgot.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: ForgotCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var ForgotCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    ForgotCtrl = $controller('ForgotCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/forgot/forgot.css",
    "content": ""
  },
  {
    "path": "example/dashboard-app/client/app/forgot/forgot.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Forgot Password</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-password-reset-request-form></div>\n</div>"
  },
  {
    "path": "example/dashboard-app/client/app/forgot/forgot.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('forgot', {\n        url: '/forgot',\n        templateUrl: 'app/forgot/forgot.html',\n        controller: 'ForgotCtrl'\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/login/login.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('LoginCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/login/login.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: LoginCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var LoginCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    LoginCtrl = $controller('LoginCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/login/login.css",
    "content": ""
  },
  {
    "path": "example/dashboard-app/client/app/login/login.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Login</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-login-form></div>\n</div>"
  },
  {
    "path": "example/dashboard-app/client/app/login/login.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('login', {\n        url: '/login',\n        templateUrl: 'app/login/login.html',\n        controller: 'LoginCtrl'\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/main/main.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('MainCtrl', function ($scope, $http) {\n    $scope.awesomeThings = [];\n\n    $http.get('/api/things').success(function(awesomeThings) {\n      $scope.awesomeThings = awesomeThings;\n    });\n\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/main/main.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: MainCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var MainCtrl,\n      scope,\n      $httpBackend;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function (_$httpBackend_, $controller, $rootScope) {\n    $httpBackend = _$httpBackend_;\n    $httpBackend.expectGET('/api/things')\n      .respond(['HTML5 Boilerplate', 'AngularJS', 'Karma', 'Express']);\n\n    scope = $rootScope.$new();\n    MainCtrl = $controller('MainCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should attach a list of things to the scope', function () {\n    $httpBackend.flush();\n    expect(scope.awesomeThings.length).toBe(4);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/main/main.css",
    "content": ".thing-form {\n    margin: 20px 0;\n}\n\n#banner {\n    border-bottom: none;\n    margin-top: -20px;\n}\n\n#banner h1 {\n    font-size: 60px;\n    line-height: 1;\n    letter-spacing: -1px;\n}\n\n.hero-unit {\n    position: relative;\n    padding: 30px 15px;\n    color: #F5F5F5;\n    text-align: center;\n    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);\n    background: #4393B9;\n}\n\n.footer {\n    text-align: center;\n    padding: 30px 0;\n    margin-top: 70px;\n    border-top: 1px solid #E5E5E5;\n}"
  },
  {
    "path": "example/dashboard-app/client/app/main/main.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<header class=\"hero-unit\" id=\"banner\">\n  <div class=\"container\">\n    <h1>'Allo, 'Allo!</h1>\n    <p class=\"lead\">Kick-start your next web app with Angular Fullstack</p>\n    <img src=\"assets/images/yeoman.png\" alt=\"I'm Yeoman\">\n  </div>\n</header>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-lg-12\">\n      <h1 class=\"page-header\">Features:</h1>\n      <ul class=\"nav nav-tabs nav-stacked col-md-4 col-lg-4 col-sm-6\" ng-repeat=\"thing in awesomeThings\">\n        <li><a href=\"#\" tooltip=\"{{thing.info}}\">{{thing.name}}</a></li>\n      </ul>\n    </div>\n  </div>\n</div>\n\n<footer class=\"footer\">\n  <div class=\"container\">\n      <p>Angular Fullstack v2.0.13 |\n        <a href=\"https://twitter.com/tyhenkel\">@tyhenkel</a> |\n         <a href=\"https://github.com/DaftMonk/generator-angular-fullstack/issues?state=open\">Issues</a></p>\n  </div>\n</footer>\n"
  },
  {
    "path": "example/dashboard-app/client/app/main/main.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('main', {\n        url: '/',\n        templateUrl: 'app/main/main.html',\n        controller: 'MainCtrl'\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/profile/profile.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('ProfileCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/profile/profile.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: ProfileCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var ProfileCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    ProfileCtrl = $controller('ProfileCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/profile/profile.css",
    "content": ""
  },
  {
    "path": "example/dashboard-app/client/app/profile/profile.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>My Profile</h3>\n      <hr>\n    </div>\n\n  </div>\n\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <pre ng-bind=\"user | json\"></pre>\n    </div>\n  </div>\n</div>"
  },
  {
    "path": "example/dashboard-app/client/app/profile/profile.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('profile', {\n        url: '/profile',\n        templateUrl: 'app/profile/profile.html',\n        controller: 'ProfileCtrl',\n        sp: {\n          authenticate: true\n        }\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/register/register.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('RegisterCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/register/register.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: RegisterCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var RegisterCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    RegisterCtrl = $controller('RegisterCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/register/register.css",
    "content": ""
  },
  {
    "path": "example/dashboard-app/client/app/register/register.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Registration</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-registration-form post-login-state=\"main\"></div>\n</div>"
  },
  {
    "path": "example/dashboard-app/client/app/register/register.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('register', {\n        url: '/register',\n        templateUrl: 'app/register/register.html',\n        controller: 'RegisterCtrl'\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/reset/reset.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('ResetCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/reset/reset.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: ResetCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var ResetCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    ResetCtrl = $controller('ResetCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/reset/reset.css",
    "content": ""
  },
  {
    "path": "example/dashboard-app/client/app/reset/reset.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Reset Your Password</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-password-reset-form></div>\n</div>"
  },
  {
    "path": "example/dashboard-app/client/app/reset/reset.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('reset', {\n        url: '/reset?sptoken',\n        templateUrl: 'app/reset/reset.html',\n        controller: 'ResetCtrl'\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/app/verify/verify.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('VerifyCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/dashboard-app/client/app/verify/verify.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: VerifyCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var VerifyCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    VerifyCtrl = $controller('VerifyCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/client/app/verify/verify.css",
    "content": ""
  },
  {
    "path": "example/dashboard-app/client/app/verify/verify.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Verify Your Account</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-email-verification></div>\n</div>"
  },
  {
    "path": "example/dashboard-app/client/app/verify/verify.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($stateProvider) {\n    $stateProvider\n      .state('verify', {\n        url: '/verify?sptoken',\n        templateUrl: 'app/verify/verify.html',\n        controller: 'VerifyCtrl'\n      });\n  });"
  },
  {
    "path": "example/dashboard-app/client/components/navbar/navbar.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('NavbarCtrl', function ($scope, $location) {\n    $scope.menu = [{\n      'title': 'Home',\n      'link': '/'\n    }];\n\n    $scope.isCollapsed = true;\n\n    $scope.isActive = function(route) {\n      return route === $location.path();\n    };\n  });"
  },
  {
    "path": "example/dashboard-app/client/components/navbar/navbar.html",
    "content": "<div class=\"navbar navbar-default navbar-static-top\" ng-controller=\"NavbarCtrl\">\n  <div class=\"container\">\n    <div class=\"navbar-header\">\n      <button class=\"navbar-toggle\" type=\"button\" ng-click=\"isCollapsed = !isCollapsed\">\n        <span class=\"sr-only\">Toggle navigation</span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n      </button>\n      <a href=\"/\" class=\"navbar-brand\">dashboard</a>\n    </div>\n    <div collapse=\"isCollapsed\" class=\"navbar-collapse collapse\" id=\"navbar-main\">\n      <ul class=\"nav navbar-nav\">\n        <li ng-repeat=\"item in menu\" ng-class=\"{active: isActive(item.link)}\">\n            <a ng-href=\"{{item.link}}\">{{item.title}}</a>\n        </li>\n        <li if-user ng-class=\"{active: isActive('/profile')}\">\n            <a ui-sref=\"profile\">Profile</a>\n        </li>\n        <li if-not-user ng-class=\"{active: isActive('/register')}\">\n            <a ui-sref=\"register\">Register</a>\n        </li>\n        <li if-not-user ng-class=\"{active: isActive('/login')}\">\n            <a ui-sref=\"login\">Login</a>\n        </li>\n        <li if-user ng-class=\"{active: isActive('/logout')}\">\n            <a ui-sref=\"main\" sp-logout>Logout</a>\n        </li>\n      </ul>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "example/dashboard-app/client/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <base href=\"/\">\n    <title></title>\n    <meta name=\"description\" content=\"\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->\n    <!-- build:css(client) app/vendor.css -->\n      <!-- bower:css -->\n      <link rel=\"stylesheet\" href=\"bower_components/bootstrap/dist/css/bootstrap.css\" />\n      <!-- endbower -->\n    <!-- endbuild -->\n    <!-- build:css({.tmp,client}) app/app.css -->\n    <link rel=\"stylesheet\" href=\"app/app.css\">\n      <!-- injector:css -->\n      <link rel=\"stylesheet\" href=\"app/app.css\">\n      <link rel=\"stylesheet\" href=\"app/forgot/forgot.css\">\n      <link rel=\"stylesheet\" href=\"app/login/login.css\">\n      <link rel=\"stylesheet\" href=\"app/main/main.css\">\n      <link rel=\"stylesheet\" href=\"app/profile/profile.css\">\n      <link rel=\"stylesheet\" href=\"app/register/register.css\">\n      <link rel=\"stylesheet\" href=\"app/reset/reset.css\">\n      <link rel=\"stylesheet\" href=\"app/verify/verify.css\">\n      <!-- endinjector -->\n    <!-- endbuild -->\n  </head>\n  <body ng-app=\"dashboardApp\">\n    <!--[if lt IE 7]>\n      <p class=\"browsehappy\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> to improve your experience.</p>\n    <![endif]-->\n\n    <!-- Add your site or application content here -->\n    <div ui-view=\"\"></div>\n\n    <!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->\n    <script>\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-XXXXX-X');\n      ga('send', 'pageview');\n    </script>\n\n    <!--[if lt IE 9]>\n    <script src=\"bower_components/es5-shim/es5-shim.js\"></script>\n    <script src=\"bower_components/json3/lib/json3.min.js\"></script>\n    <![endif]-->\n    <!-- build:js({client,node_modules}) app/vendor.js -->\n      <!-- bower:js -->\n      <script src=\"bower_components/jquery/dist/jquery.js\"></script>\n      <script src=\"bower_components/angular/angular.js\"></script>\n      <script src=\"bower_components/angular-resource/angular-resource.js\"></script>\n      <script src=\"bower_components/angular-cookies/angular-cookies.js\"></script>\n      <script src=\"bower_components/angular-sanitize/angular-sanitize.js\"></script>\n      <script src=\"bower_components/lodash/dist/lodash.compat.js\"></script>\n      <script src=\"bower_components/angular-ui-router/release/angular-ui-router.js\"></script>\n      <script src=\"bower_components/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.min.js\"></script>\n      <script src=\"bower_components/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.tpls.min.js\"></script>\n      <!-- endbower -->\n    <!-- endbuild -->\n\n        <!-- build:js({.tmp,client}) app/app.js -->\n        <script src=\"app/app.js\"></script>\n          <!-- injector:js -->\n          <script src=\"app/forgot/forgot.controller.js\"></script>\n          <script src=\"app/forgot/forgot.js\"></script>\n          <script src=\"app/login/login.controller.js\"></script>\n          <script src=\"app/login/login.js\"></script>\n          <script src=\"app/main/main.controller.js\"></script>\n          <script src=\"app/main/main.js\"></script>\n          <script src=\"app/profile/profile.controller.js\"></script>\n          <script src=\"app/profile/profile.js\"></script>\n          <script src=\"app/register/register.controller.js\"></script>\n          <script src=\"app/register/register.js\"></script>\n          <script src=\"app/reset/reset.controller.js\"></script>\n          <script src=\"app/reset/reset.js\"></script>\n          <script src=\"app/verify/verify.controller.js\"></script>\n          <script src=\"app/verify/verify.js\"></script>\n          <script src=\"components/navbar/navbar.controller.js\"></script>\n          <!-- endinjector -->\n        <!-- endbuild -->\n</body>\n</html>\n"
  },
  {
    "path": "example/dashboard-app/client/robots.txt",
    "content": "# robotstxt.org\n\nUser-agent: *\n"
  },
  {
    "path": "example/dashboard-app/e2e/main/main.po.js",
    "content": "/**\n * This file uses the Page Object pattern to define the main page for tests\n * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ\n */\n\n'use strict';\n\nvar MainPage = function() {\n  this.heroEl = element(by.css('.hero-unit'));\n  this.h1El = this.heroEl.element(by.css('h1'));\n  this.imgEl = this.heroEl.element(by.css('img'));\n};\n\nmodule.exports = new MainPage();\n\n"
  },
  {
    "path": "example/dashboard-app/e2e/main/main.spec.js",
    "content": "'use strict';\n\ndescribe('Main View', function() {\n  var page;\n\n  beforeEach(function() {\n    browser.get('/');\n    page = require('./main.po');\n  });\n\n  it('should include jumbotron with correct data', function() {\n    expect(page.h1El.getText()).toBe('\\'Allo, \\'Allo!');\n    expect(page.imgEl.getAttribute('src')).toMatch(/assets\\/images\\/yeoman.png$/);\n    expect(page.imgEl.getAttribute('alt')).toBe('I\\'m Yeoman');\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/karma.conf.js",
    "content": "// Karma configuration\n// http://karma-runner.github.io/0.10/config/configuration-file.html\n\nmodule.exports = function(config) {\n  config.set({\n    // base path, that will be used to resolve files and exclude\n    basePath: '',\n\n    // testing framework to use (jasmine/mocha/qunit/...)\n    frameworks: ['jasmine'],\n\n    // list of files / patterns to load in the browser\n    files: [\n      'client/bower_components/jquery/dist/jquery.js',\n      'client/bower_components/angular/angular.js',\n      'client/bower_components/angular-mocks/angular-mocks.js',\n      'client/bower_components/angular-resource/angular-resource.js',\n      'client/bower_components/angular-cookies/angular-cookies.js',\n      'client/bower_components/angular-sanitize/angular-sanitize.js',\n      'client/bower_components/angular-route/angular-route.js',\n      'client/bower_components/lodash/dist/lodash.compat.js',\n      'client/bower_components/angular-ui-router/release/angular-ui-router.js',\n      'client/app/app.js',\n      'client/app/app.coffee',\n      'client/app/**/*.js',\n      'client/app/**/*.coffee',\n      'client/components/**/*.js',\n      'client/components/**/*.coffee',\n      'client/app/**/*.jade',\n      'client/components/**/*.jade',\n      'client/app/**/*.html',\n      'client/components/**/*.html'\n    ],\n\n    preprocessors: {\n      '**/*.jade': 'ng-jade2js',\n      '**/*.html': 'html2js',\n      '**/*.coffee': 'coffee',\n    },\n\n    ngHtml2JsPreprocessor: {\n      stripPrefix: 'client/'\n    },\n\n    ngJade2JsPreprocessor: {\n      stripPrefix: 'client/'\n    },\n\n    // list of files / patterns to exclude\n    exclude: [],\n\n    // web server port\n    port: 8080,\n\n    // level of logging\n    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG\n    logLevel: config.LOG_INFO,\n\n\n    // enable / disable watching file and executing tests whenever any file changes\n    autoWatch: false,\n\n\n    // Start these browsers, currently available:\n    // - Chrome\n    // - ChromeCanary\n    // - Firefox\n    // - Opera\n    // - Safari (only Mac)\n    // - PhantomJS\n    // - IE (only Windows)\n    browsers: ['PhantomJS'],\n\n\n    // Continuous Integration mode\n    // if true, it capture browsers, run tests and exit\n    singleRun: false\n  });\n};\n"
  },
  {
    "path": "example/dashboard-app/package.json",
    "content": "{\n  \"name\": \"dashboard\",\n  \"version\": \"0.0.0\",\n  \"main\": \"server/app.js\",\n  \"dependencies\": {\n    \"body-parser\": \"~1.5.0\",\n    \"composable-middleware\": \"^0.3.0\",\n    \"compression\": \"~1.0.1\",\n    \"connect-mongo\": \"^0.4.1\",\n    \"cookie-parser\": \"~1.0.1\",\n    \"ejs\": \"~0.8.4\",\n    \"errorhandler\": \"~1.0.0\",\n    \"express\": \"^4.13.3\",\n    \"express-session\": \"~1.0.2\",\n    \"express-stormpath\": \"^3.0.0\",\n    \"lodash\": \"~2.4.1\",\n    \"method-override\": \"~1.0.0\",\n    \"morgan\": \"~1.0.0\",\n    \"serve-favicon\": \"~2.0.1\"\n  },\n  \"devDependencies\": {\n    \"grunt\": \"~0.4.4\",\n    \"grunt-autoprefixer\": \"~0.7.2\",\n    \"grunt-wiredep\": \"~1.8.0\",\n    \"grunt-concurrent\": \"~0.5.0\",\n    \"grunt-contrib-clean\": \"~0.5.0\",\n    \"grunt-contrib-concat\": \"~0.4.0\",\n    \"grunt-contrib-copy\": \"~0.5.0\",\n    \"grunt-contrib-cssmin\": \"~0.9.0\",\n    \"grunt-contrib-htmlmin\": \"~0.2.0\",\n    \"grunt-contrib-imagemin\": \"~0.7.1\",\n    \"grunt-contrib-jshint\": \"~0.10.0\",\n    \"grunt-contrib-uglify\": \"~0.4.0\",\n    \"grunt-contrib-watch\": \"~0.6.1\",\n    \"grunt-google-cdn\": \"~0.4.0\",\n    \"grunt-newer\": \"~0.7.0\",\n    \"grunt-ng-annotate\": \"^0.2.3\",\n    \"grunt-rev\": \"~0.1.0\",\n    \"grunt-svgmin\": \"~0.4.0\",\n    \"grunt-usemin\": \"~2.1.1\",\n    \"grunt-env\": \"~0.4.1\",\n    \"grunt-node-inspector\": \">=0.2.0\",\n    \"grunt-nodemon\": \"~0.2.0\",\n    \"grunt-angular-templates\": \"^0.5.4\",\n    \"grunt-dom-munger\": \"^3.4.0\",\n    \"grunt-protractor-runner\": \"^1.1.0\",\n    \"grunt-asset-injector\": \"^0.1.0\",\n    \"grunt-karma\": \"~0.8.2\",\n    \"grunt-build-control\": \"DaftMonk/grunt-build-control\",\n    \"grunt-mocha-test\": \"~0.10.2\",\n    \"jit-grunt\": \"^0.5.0\",\n    \"time-grunt\": \"~0.3.1\",\n    \"grunt-express-server\": \"~0.4.17\",\n    \"grunt-open\": \"~0.2.3\",\n    \"open\": \"~0.0.4\",\n    \"jshint-stylish\": \"~0.1.5\",\n    \"connect-livereload\": \"~0.4.0\",\n    \"karma-ng-scenario\": \"~0.1.0\",\n    \"karma-firefox-launcher\": \"~0.1.3\",\n    \"karma-script-launcher\": \"~0.1.0\",\n    \"karma-html2js-preprocessor\": \"~0.1.0\",\n    \"karma-ng-jade2js-preprocessor\": \"^0.1.2\",\n    \"karma-jasmine\": \"~0.1.5\",\n    \"karma-chrome-launcher\": \"~0.1.3\",\n    \"requirejs\": \"~2.1.11\",\n    \"karma-requirejs\": \"~0.2.1\",\n    \"karma-coffee-preprocessor\": \"~0.2.1\",\n    \"karma-jade-preprocessor\": \"0.0.11\",\n    \"karma-phantomjs-launcher\": \"~0.1.4\",\n    \"karma\": \"~0.12.9\",\n    \"karma-ng-html2js-preprocessor\": \"~0.1.0\",\n    \"supertest\": \"~0.11.0\",\n    \"should\": \"~3.3.1\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server/app.js\",\n    \"test\": \"grunt test\",\n    \"update-webdriver\": \"node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update\"\n  },\n  \"private\": true\n}\n"
  },
  {
    "path": "example/dashboard-app/protractor.conf.js",
    "content": "// Protractor configuration\n// https://github.com/angular/protractor/blob/master/referenceConf.js\n\n'use strict';\n\nexports.config = {\n  // The timeout for each script run on the browser. This should be longer\n  // than the maximum time your application needs to stabilize between tasks.\n  allScriptsTimeout: 110000,\n\n  // A base URL for your application under test. Calls to protractor.get()\n  // with relative paths will be prepended with this.\n  baseUrl: 'http://localhost:' + (process.env.PORT || '9000'),\n\n  // If true, only chromedriver will be started, not a standalone selenium.\n  // Tests for browsers other than chrome will not run.\n  chromeOnly: true,\n\n  // list of files / patterns to load in the browser\n  specs: [\n    'e2e/**/*.spec.js'\n  ],\n\n  // Patterns to exclude.\n  exclude: [],\n\n  // ----- Capabilities to be passed to the webdriver instance ----\n  //\n  // For a full list of available capabilities, see\n  // https://code.google.com/p/selenium/wiki/DesiredCapabilities\n  // and\n  // https://code.google.com/p/selenium/source/browse/javascript/webdriver/capabilities.js\n  capabilities: {\n    'browserName': 'chrome'\n  },\n\n  // ----- The test framework -----\n  //\n  // Jasmine and Cucumber are fully supported as a test and assertion framework.\n  // Mocha has limited beta support. You will need to include your own\n  // assertion framework if working with mocha.\n  framework: 'jasmine',\n\n  // ----- Options to be passed to minijasminenode -----\n  //\n  // See the full list at https://github.com/juliemr/minijasminenode\n  jasmineNodeOpts: {\n    defaultTimeoutInterval: 30000\n  }\n};\n"
  },
  {
    "path": "example/dashboard-app/server/.jshintrc",
    "content": "{\n  \"node\": true,\n  \"esnext\": true,\n  \"bitwise\": true,\n  \"eqeqeq\": true,\n  \"immed\": true,\n  \"latedef\": \"nofunc\",\n  \"newcap\": true,\n  \"noarg\": true,\n  \"regexp\": true,\n  \"undef\": true,\n  \"smarttabs\": true,\n  \"asi\": true,\n  \"debug\": true\n}\n"
  },
  {
    "path": "example/dashboard-app/server/.jshintrc-spec",
    "content": "{\n  \"extends\": \".jshintrc\",\n  \"globals\": {\n    \"describe\": true,\n    \"it\": true,\n    \"before\": true,\n    \"beforeEach\": true,\n    \"after\": true,\n    \"afterEach\": true\n  }\n}\n"
  },
  {
    "path": "example/dashboard-app/server/api/thing/index.js",
    "content": "'use strict';\n\nvar express = require('express');\nvar controller = require('./thing.controller');\n\nvar router = express.Router();\n\nrouter.get('/', controller.index);\n\nmodule.exports = router;"
  },
  {
    "path": "example/dashboard-app/server/api/thing/thing.controller.js",
    "content": "/**\n * Using Rails-like standard naming convention for endpoints.\n * GET     /things              ->  index\n * POST    /things              ->  create\n * GET     /things/:id          ->  show\n * PUT     /things/:id          ->  update\n * DELETE  /things/:id          ->  destroy\n */\n\n'use strict';\n\nvar _ = require('lodash');\n\n// Get list of things\nexports.index = function(req, res) {\n  res.json([\n  {\n  name : 'Development Tools',\n  info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.'\n  }, {\n  name : 'Server and Client integration',\n  info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.'\n  }, {\n  name : 'Smart Build System',\n  info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. Automatic injection of scripts and styles into your index.html'\n  },  {\n  name : 'Modular Structure',\n  info : 'Best practice client and server structures allow for more code reusability and maximum scalability'\n  },  {\n  name : 'Optimized Build',\n  info : 'Build process packs up your templates as a single JavaScript payload, minifies your scripts/css/images, and rewrites asset names for caching.'\n  },{\n  name : 'Deployment Ready',\n  info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators'\n  }\n  ]);\n};"
  },
  {
    "path": "example/dashboard-app/server/api/thing/thing.spec.js",
    "content": "'use strict';\n\nvar should = require('should');\nvar app = require('../../app');\nvar request = require('supertest');\n\ndescribe('GET /api/things', function() {\n\n  it('should respond with JSON array', function(done) {\n    request(app)\n      .get('/api/things')\n      .expect(200)\n      .expect('Content-Type', /json/)\n      .end(function(err, res) {\n        if (err) return done(err);\n        res.body.should.be.instanceof(Array);\n        done();\n      });\n  });\n});\n"
  },
  {
    "path": "example/dashboard-app/server/app.js",
    "content": "/**\n * Main application file\n */\n\n'use strict';\n\n// Set default node environment to development\nprocess.env.NODE_ENV = process.env.NODE_ENV || 'development';\n\nvar express = require('express');\nvar config = require('./config/environment');\nvar ExpressStormpath = require('express-stormpath');\n\n// Setup server\nvar app = express();\n\nvar server = require('http').createServer(app);\n\n/*\n  The config/express file is setting up the static file server which serves your\n  angular application assets.  We don't need to authenticate those requests, so\n  we do this before calling Stormpath.\n */\n\nrequire('./config/express')(app);\n\nconsole.log('Initializing Stormpath');\n\n/*\n  Now we initialize Stormpath, any middleware that is registered after this\n  point will be protected by Stormpath.\n\n  The spa setting tells the Stormpath library where your Angular app is,\n  as it will need to serve it for the default routes like /login and\n  /register.  The appPath property is provided by the configuration parser\n  in the Yeoman boilerplate.\n */\n\napp.use(ExpressStormpath.init(app,{\n  web: {\n    produces: ['application/json'],\n    spa: {\n      enabled: true,\n      view: app.get('appPath')\n    },\n    register: {\n      form: {\n        fields: {\n          /*\n            We can define custom form fields here, and they will appear in the\n            front-end.  The Angular SDK will read this registration view model\n            from the Express server by making a JSON GET request to /register\n           */\n          favoriteColor: {\n            enabled: true,\n            label: 'Favorite Color?',\n            placeholder: 'e.g. Blue',\n            required: true,\n            type: 'text'\n          }\n        }\n      }\n    },\n    me: {\n      /*\n        For security purposes, we don't expose user information by default.  To\n        facilitate our Profile page example, we will need to enable the\n        expansion of the user's custom data object.\n       */\n      expand: {\n        customData: true\n      }\n    }\n  }\n}));\n\n\nrequire('./routes')(app);\n\napp.on('stormpath.ready',function() {\n  console.log('Stormpath Ready');\n});\n\n// Start server\nserver.listen(config.port, config.ip, function () {\n  console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));\n});\n\n\n// Expose app\nexports = module.exports = app;\n"
  },
  {
    "path": "example/dashboard-app/server/components/errors/index.js",
    "content": "/**\n * Error responses\n */\n\n'use strict';\n\nmodule.exports[404] = function pageNotFound(req, res) {\n  var viewFilePath = '404';\n  var statusCode = 404;\n  var result = {\n    status: statusCode\n  };\n\n  res.status(result.status);\n  res.render(viewFilePath, function (err) {\n    if (err) { return res.json(result, result.status); }\n\n    res.render(viewFilePath);\n  });\n};\n"
  },
  {
    "path": "example/dashboard-app/server/config/environment/development.js",
    "content": "'use strict';\n\n// Development specific configuration\n// ==================================\nmodule.exports = {\n  // MongoDB connection options\n  mongo: {\n    uri: 'mongodb://localhost/dashboard-dev'\n  },\n\n  seedDB: true\n};\n"
  },
  {
    "path": "example/dashboard-app/server/config/environment/index.js",
    "content": "'use strict';\n\nvar path = require('path');\nvar _ = require('lodash');\n\nfunction requiredProcessEnv(name) {\n  if(!process.env[name]) {\n    throw new Error('You must set the ' + name + ' environment variable');\n  }\n  return process.env[name];\n}\n\n// All configurations will extend these options\n// ============================================\nvar all = {\n  env: process.env.NODE_ENV,\n\n  // Root path of server\n  root: path.normalize(__dirname + '/../../..'),\n\n  // Server port\n  port: process.env.PORT || 9000,\n\n  // Should we populate the DB with sample data?\n  seedDB: false,\n\n  // Secret for session, you will want to change this and make it an environment variable\n  secrets: {\n    session: 'dashboard-secret'\n  },\n\n  // List of user roles\n  userRoles: ['guest', 'user', 'admin'],\n\n  // MongoDB connection options\n  mongo: {\n    options: {\n      db: {\n        safe: true\n      }\n    }\n  },\n\n};\n\n// Export the config object based on the NODE_ENV\n// ==============================================\nmodule.exports = _.merge(\n  all,\n  require('./' + process.env.NODE_ENV + '.js') || {});"
  },
  {
    "path": "example/dashboard-app/server/config/environment/production.js",
    "content": "'use strict';\n\n// Production specific configuration\n// =================================\nmodule.exports = {\n  // Server IP\n  ip:       process.env.OPENSHIFT_NODEJS_IP ||\n            process.env.IP ||\n            undefined,\n\n  // Server port\n  port:     process.env.OPENSHIFT_NODEJS_PORT ||\n            process.env.PORT ||\n            8080,\n\n  // MongoDB connection options\n  mongo: {\n    uri:    process.env.MONGOLAB_URI ||\n            process.env.MONGOHQ_URL ||\n            process.env.OPENSHIFT_MONGODB_DB_URL+process.env.OPENSHIFT_APP_NAME ||\n            'mongodb://localhost/dashboard'\n  }\n};"
  },
  {
    "path": "example/dashboard-app/server/config/environment/test.js",
    "content": "'use strict';\n\n// Test specific configuration\n// ===========================\nmodule.exports = {\n  // MongoDB connection options\n  mongo: {\n    uri: 'mongodb://localhost/dashboard-test'\n  }\n};"
  },
  {
    "path": "example/dashboard-app/server/config/express.js",
    "content": "/**\n * Express configuration\n */\n\n'use strict';\n\nvar express = require('express');\nvar favicon = require('serve-favicon');\nvar morgan = require('morgan');\nvar compression = require('compression');\nvar bodyParser = require('body-parser');\nvar methodOverride = require('method-override');\nvar cookieParser = require('cookie-parser');\nvar errorHandler = require('errorhandler');\nvar path = require('path');\nvar config = require('./environment');\n\nmodule.exports = function(app) {\n  var env = app.get('env');\n\n  app.set('views', config.root + '/server/views');\n  app.engine('html', require('ejs').renderFile);\n  app.set('view engine', 'html');\n  app.set('trust proxy', true);\n  app.use(compression());\n  app.use(methodOverride());\n  app.use(cookieParser());\n\n  if ('production' === env) {\n    app.use(favicon(path.join(config.root, 'public', 'favicon.ico')));\n    app.use(express.static(path.join(config.root, 'public')));\n    app.set('appPath', path.join(config.root, 'public', 'index.html'));\n    app.use(morgan('dev'));\n  }\n\n  if ('development' === env || 'test' === env) {\n    app.use(require('connect-livereload')());\n    app.use(express.static(path.join(config.root, '.tmp')));\n    app.use(express.static(path.join(config.root, 'client')));\n    app.set('appPath', path.join(config.root, 'client', 'index.html'));\n    app.use(morgan('dev'));\n    app.use(errorHandler()); // Error handler - has to be last\n  }\n};\n"
  },
  {
    "path": "example/dashboard-app/server/config/local.env.sample.js",
    "content": "'use strict';\n\n// Use local.env.js for environment variables that grunt will set when the server starts locally.\n// Use for your api keys, secrets, etc. This file should not be tracked by git.\n//\n// You will need to set these on the server you deploy to.\n\nmodule.exports = {\n  DOMAIN:           'http://localhost:9000',\n  SESSION_SECRET:   'dashboard-secret',\n\n  // Control debug level for modules using visionmedia/debug\n  DEBUG: ''\n};\n"
  },
  {
    "path": "example/dashboard-app/server/routes.js",
    "content": "/**\n * Main application routes\n */\n\n'use strict';\n\nvar errors = require('./components/errors');\nvar ExpressStormpath = require('express-stormpath');\n\nmodule.exports = function(app) {\n\n  // Insert routes below\n  app.use('/api/things', ExpressStormpath.loginRequired, require('./api/thing'));\n\n  // All undefined asset or api routes should return a 404\n  app.route('/:url(api|auth|components|app|bower_components|assets)/*')\n   .get(errors[404]);\n\n  // All other routes should redirect to the index.html\n  app.route('/*')\n    .get(function(req, res) {\n      res.sendFile(app.get('appPath'));\n    });\n};\n"
  },
  {
    "path": "example/dashboard-app/server/views/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Page Not Found :(</title>\n    <style>\n      ::-moz-selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      ::selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      html {\n        padding: 30px 10px;\n        font-size: 20px;\n        line-height: 1.4;\n        color: #737373;\n        background: #f0f0f0;\n        -webkit-text-size-adjust: 100%;\n        -ms-text-size-adjust: 100%;\n      }\n\n      html,\n      input {\n        font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n      }\n\n      body {\n        max-width: 500px;\n        _width: 500px;\n        padding: 30px 20px 50px;\n        border: 1px solid #b3b3b3;\n        border-radius: 4px;\n        margin: 0 auto;\n        box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n        background: #fcfcfc;\n      }\n\n      h1 {\n        margin: 0 10px;\n        font-size: 50px;\n        text-align: center;\n      }\n\n      h1 span {\n        color: #bbb;\n      }\n\n      h3 {\n        margin: 1.5em 0 0.5em;\n      }\n\n      p {\n        margin: 1em 0;\n      }\n\n      ul {\n        padding: 0 0 0 40px;\n        margin: 1em 0;\n      }\n\n      .container {\n        max-width: 380px;\n        _width: 380px;\n        margin: 0 auto;\n      }\n\n      /* google search */\n\n      #goog-fixurl ul {\n        list-style: none;\n        padding: 0;\n        margin: 0;\n      }\n\n      #goog-fixurl form {\n        margin: 0;\n      }\n\n      #goog-wm-qt,\n      #goog-wm-sb {\n        border: 1px solid #bbb;\n        font-size: 16px;\n        line-height: normal;\n        vertical-align: top;\n        color: #444;\n        border-radius: 2px;\n      }\n\n      #goog-wm-qt {\n        width: 220px;\n        height: 20px;\n        padding: 5px;\n        margin: 5px 10px 0 0;\n        box-shadow: inset 0 1px 1px #ccc;\n      }\n\n      #goog-wm-sb {\n        display: inline-block;\n        height: 32px;\n        padding: 0 10px;\n        margin: 5px 0 0;\n        white-space: nowrap;\n        cursor: pointer;\n        background-color: #f5f5f5;\n        background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        -webkit-appearance: none;\n        -moz-appearance: none;\n        appearance: none;\n        *overflow: visible;\n        *display: inline;\n        *zoom: 1;\n      }\n\n      #goog-wm-sb:hover,\n      #goog-wm-sb:focus {\n        border-color: #aaa;\n        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n        background-color: #f8f8f8;\n      }\n\n      #goog-wm-qt:hover,\n      #goog-wm-qt:focus {\n        border-color: #105cb6;\n        outline: 0;\n        color: #222;\n      }\n\n      input::-moz-focus-inner {\n        padding: 0;\n        border: 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <h1>Not found <span>:(</span></h1>\n      <p>Sorry, but the page you were trying to view does not exist.</p>\n      <p>It looks like this was the result of either:</p>\n      <ul>\n        <li>a mistyped address</li>\n        <li>an out-of-date link</li>\n      </ul>\n      <script>\n        var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n      </script>\n      <script src=\"//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "example/ng-route-app/.bowerrc",
    "content": "{\n    \"directory\": \"client/bower_components\"\n}\n"
  },
  {
    "path": "example/ng-route-app/.buildignore",
    "content": "*.coffee"
  },
  {
    "path": "example/ng-route-app/.editorconfig",
    "content": "# EditorConfig helps developers define and maintain consistent\n# coding styles between different editors and IDEs\n# editorconfig.org\n\nroot = true\n\n\n[*]\n\n# Change these settings to your own preference\nindent_style = space\nindent_size = 2\n\n# We recommend you to keep these unchanged\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": "example/ng-route-app/.gitattributes",
    "content": "* text=auto"
  },
  {
    "path": "example/ng-route-app/.gitignore",
    "content": "node_modules\npublic\n.tmp\n.idea\nclient/bower_components\ndist\n/server/config/local.env.js\nstormpath.yml\n"
  },
  {
    "path": "example/ng-route-app/.travis.yml",
    "content": "language: node_js\nnode_js:\n  - '0.10'\n  - '0.11'\nbefore_script:\n  - npm install -g bower grunt-cli\n  - bower install\nservices: mongodb"
  },
  {
    "path": "example/ng-route-app/.yo-rc.json",
    "content": "{\n  \"generator-angular-fullstack\": {\n    \"insertRoutes\": true,\n    \"registerRoutesFile\": \"server/routes.js\",\n    \"routesNeedle\": \"// Insert routes below\",\n    \"routesBase\": \"/api/\",\n    \"pluralizeRoutes\": true,\n    \"insertSockets\": true,\n    \"registerSocketsFile\": \"server/config/socketio.js\",\n    \"socketsNeedle\": \"// Insert sockets below\",\n    \"filters\": {\n      \"js\": true,\n      \"html\": true,\n      \"css\": true,\n      \"uirouter\": true,\n      \"bootstrap\": true,\n      \"uibootstrap\": false\n    }\n  },\n  \"generator-ng-component\": {\n    \"routeDirectory\": \"client/app/\",\n    \"directiveDirectory\": \"client/app/\",\n    \"filterDirectory\": \"client/app/\",\n    \"serviceDirectory\": \"client/app/\",\n    \"basePath\": \"client\",\n    \"moduleName\": \"\",\n    \"filters\": [\n      \"uirouter\"\n    ],\n    \"extensions\": [\n      \"js\",\n      \"html\",\n      \"css\"\n    ],\n    \"directiveSimpleTemplates\": \"\",\n    \"directiveComplexTemplates\": \"\",\n    \"filterTemplates\": \"\",\n    \"serviceTemplates\": \"\",\n    \"factoryTemplates\": \"\",\n    \"controllerTemplates\": \"\",\n    \"decoratorTemplates\": \"\",\n    \"providerTemplates\": \"\",\n    \"routeTemplates\": \"\"\n  }\n}"
  },
  {
    "path": "example/ng-route-app/Gruntfile.js",
    "content": "// Generated on 2015-09-24 using generator-angular-fullstack 2.0.13\n'use strict';\n\nmodule.exports = function (grunt) {\n  var localConfig;\n  try {\n    localConfig = require('./server/config/local.env');\n  } catch(e) {\n    localConfig = {};\n  }\n\n  // Load grunt tasks automatically, when needed\n  require('jit-grunt')(grunt, {\n    express: 'grunt-express-server',\n    useminPrepare: 'grunt-usemin',\n    ngtemplates: 'grunt-angular-templates',\n    cdnify: 'grunt-google-cdn',\n    protractor: 'grunt-protractor-runner',\n    injector: 'grunt-asset-injector',\n    buildcontrol: 'grunt-build-control'\n  });\n\n  // Time how long tasks take. Can help when optimizing build times\n  require('time-grunt')(grunt);\n\n  // Define the configuration for all the tasks\n  grunt.initConfig({\n\n    // Project settings\n    pkg: grunt.file.readJSON('package.json'),\n    yeoman: {\n      // configurable paths\n      client: require('./bower.json').appPath || 'client',\n      dist: 'dist'\n    },\n    express: {\n      options: {\n        port: process.env.PORT || 9000,\n        // output option will force Grunt to wait for this\n        // line to be seen in server output, before continuing\n        output: 'Stormpath Ready'\n      },\n      dev: {\n        options: {\n          script: 'server/app.js',\n          debug: true\n        }\n      },\n      prod: {\n        options: {\n          script: 'dist/server/app.js'\n        }\n      }\n    },\n    open: {\n      server: {\n        url: 'http://localhost:<%= express.options.port %>'\n      }\n    },\n    watch: {\n      injectJS: {\n        files: [\n          '<%= yeoman.client %>/{app,components}/**/*.js',\n          '!<%= yeoman.client %>/{app,components}/**/*.spec.js',\n          '!<%= yeoman.client %>/{app,components}/**/*.mock.js',\n          '!<%= yeoman.client %>/app/app.js'],\n        tasks: ['injector:scripts']\n      },\n      injectCss: {\n        files: [\n          '<%= yeoman.client %>/{app,components}/**/*.css'\n        ],\n        tasks: ['injector:css']\n      },\n      mochaTest: {\n        files: ['server/**/*.spec.js'],\n        tasks: ['env:test', 'mochaTest']\n      },\n      jsTest: {\n        files: [\n          '<%= yeoman.client %>/{app,components}/**/*.spec.js',\n          '<%= yeoman.client %>/{app,components}/**/*.mock.js'\n        ],\n        tasks: ['newer:jshint:all', 'karma']\n      },\n      gruntfile: {\n        files: ['Gruntfile.js']\n      },\n      livereload: {\n        files: [\n          '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.css',\n          '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.html',\n          '{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',\n          '!{.tmp,<%= yeoman.client %>}{app,components}/**/*.spec.js',\n          '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js',\n          '<%= yeoman.client %>/assets/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}'\n        ],\n        options: {\n          livereload: true\n        }\n      },\n      express: {\n        files: [\n          'server/**/*.{js,json}'\n        ],\n        tasks: ['express:dev', 'wait'],\n        options: {\n          livereload: true,\n          nospawn: true //Without this option specified express won't be reloaded\n        }\n      }\n    },\n\n    // Make sure code styles are up to par and there are no obvious mistakes\n    jshint: {\n      options: {\n        jshintrc: '<%= yeoman.client %>/.jshintrc',\n        reporter: require('jshint-stylish')\n      },\n      server: {\n        options: {\n          jshintrc: 'server/.jshintrc'\n        },\n        src: [\n          'server/**/*.js',\n          '!server/**/*.spec.js'\n        ]\n      },\n      serverTest: {\n        options: {\n          jshintrc: 'server/.jshintrc-spec'\n        },\n        src: ['server/**/*.spec.js']\n      },\n      all: [\n        '<%= yeoman.client %>/{app,components}/**/*.js',\n        '!<%= yeoman.client %>/{app,components}/**/*.spec.js',\n        '!<%= yeoman.client %>/{app,components}/**/*.mock.js'\n      ],\n      test: {\n        src: [\n          '<%= yeoman.client %>/{app,components}/**/*.spec.js',\n          '<%= yeoman.client %>/{app,components}/**/*.mock.js'\n        ]\n      }\n    },\n\n    // Empties folders to start fresh\n    clean: {\n      dist: {\n        files: [{\n          dot: true,\n          src: [\n            '.tmp',\n            '<%= yeoman.dist %>/*',\n            '!<%= yeoman.dist %>/.git*',\n            '!<%= yeoman.dist %>/.openshift',\n            '!<%= yeoman.dist %>/Procfile'\n          ]\n        }]\n      },\n      server: '.tmp'\n    },\n\n    // Add vendor prefixed styles\n    autoprefixer: {\n      options: {\n        browsers: ['last 1 version']\n      },\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '.tmp/',\n          src: '{,*/}*.css',\n          dest: '.tmp/'\n        }]\n      }\n    },\n\n    // Debugging with node inspector\n    'node-inspector': {\n      custom: {\n        options: {\n          'web-host': 'localhost'\n        }\n      }\n    },\n\n    // Use nodemon to run server in debug mode with an initial breakpoint\n    nodemon: {\n      debug: {\n        script: 'server/app.js',\n        options: {\n          nodeArgs: ['--debug-brk'],\n          env: {\n            PORT: process.env.PORT || 9000\n          },\n          callback: function (nodemon) {\n            nodemon.on('log', function (event) {\n              console.log(event.colour);\n            });\n\n            // opens browser on initial server start\n            nodemon.on('config:update', function () {\n              setTimeout(function () {\n                require('open')('http://localhost:8080/debug?port=5858');\n              }, 500);\n            });\n          }\n        }\n      }\n    },\n\n    // Automatically inject Bower components into the app\n    wiredep: {\n      target: {\n        src: '<%= yeoman.client %>/index.html',\n        ignorePath: '<%= yeoman.client %>/',\n        exclude: [/bootstrap-sass-official/, /bootstrap.js/, '/json3/', '/es5-shim/']\n      }\n    },\n\n    // Renames files for browser caching purposes\n    rev: {\n      dist: {\n        files: {\n          src: [\n            '<%= yeoman.dist %>/public/{,*/}*.js',\n            '<%= yeoman.dist %>/public/{,*/}*.css',\n            '<%= yeoman.dist %>/public/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',\n            '<%= yeoman.dist %>/public/assets/fonts/*'\n          ]\n        }\n      }\n    },\n\n    // Reads HTML for usemin blocks to enable smart builds that automatically\n    // concat, minify and revision files. Creates configurations in memory so\n    // additional tasks can operate on them\n    useminPrepare: {\n      html: ['<%= yeoman.client %>/index.html'],\n      options: {\n        dest: '<%= yeoman.dist %>/public'\n      }\n    },\n\n    // Performs rewrites based on rev and the useminPrepare configuration\n    usemin: {\n      html: ['<%= yeoman.dist %>/public/{,*/}*.html'],\n      css: ['<%= yeoman.dist %>/public/{,*/}*.css'],\n      js: ['<%= yeoman.dist %>/public/{,*/}*.js'],\n      options: {\n        assetsDirs: [\n          '<%= yeoman.dist %>/public',\n          '<%= yeoman.dist %>/public/assets/images'\n        ],\n        // This is so we update image references in our ng-templates\n        patterns: {\n          js: [\n            [/(assets\\/images\\/.*?\\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']\n          ]\n        }\n      }\n    },\n\n    // The following *-min tasks produce minified files in the dist folder\n    imagemin: {\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '<%= yeoman.client %>/assets/images',\n          src: '{,*/}*.{png,jpg,jpeg,gif}',\n          dest: '<%= yeoman.dist %>/public/assets/images'\n        }]\n      }\n    },\n\n    svgmin: {\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '<%= yeoman.client %>/assets/images',\n          src: '{,*/}*.svg',\n          dest: '<%= yeoman.dist %>/public/assets/images'\n        }]\n      }\n    },\n\n    // Allow the use of non-minsafe AngularJS files. Automatically makes it\n    // minsafe compatible so Uglify does not destroy the ng references\n    ngAnnotate: {\n      dist: {\n        files: [{\n          expand: true,\n          cwd: '.tmp/concat',\n          src: '*/**.js',\n          dest: '.tmp/concat'\n        }]\n      }\n    },\n\n    // Package all the html partials into a single javascript payload\n    ngtemplates: {\n      options: {\n        // This should be the name of your apps angular module\n        module: 'dashboardApp',\n        htmlmin: {\n          collapseBooleanAttributes: true,\n          collapseWhitespace: true,\n          removeAttributeQuotes: true,\n          removeEmptyAttributes: true,\n          removeRedundantAttributes: true,\n          removeScriptTypeAttributes: true,\n          removeStyleLinkTypeAttributes: true\n        },\n        usemin: 'app/app.js'\n      },\n      main: {\n        cwd: '<%= yeoman.client %>',\n        src: ['{app,components}/**/*.html'],\n        dest: '.tmp/templates.js'\n      },\n      tmp: {\n        cwd: '.tmp',\n        src: ['{app,components}/**/*.html'],\n        dest: '.tmp/tmp-templates.js'\n      }\n    },\n\n    // Replace Google CDN references\n    cdnify: {\n      dist: {\n        html: ['<%= yeoman.dist %>/public/*.html']\n      }\n    },\n\n    // Copies remaining files to places other tasks can use\n    copy: {\n      dist: {\n        files: [{\n          expand: true,\n          dot: true,\n          cwd: '<%= yeoman.client %>',\n          dest: '<%= yeoman.dist %>/public',\n          src: [\n            '*.{ico,png,txt}',\n            '.htaccess',\n            'bower_components/**/*',\n            'assets/images/{,*/}*.{webp}',\n            'assets/fonts/**/*',\n            'index.html'\n          ]\n        }, {\n          expand: true,\n          cwd: '.tmp/images',\n          dest: '<%= yeoman.dist %>/public/assets/images',\n          src: ['generated/*']\n        }, {\n          expand: true,\n          dest: '<%= yeoman.dist %>',\n          src: [\n            'package.json',\n            'server/**/*'\n          ]\n        }]\n      },\n      styles: {\n        expand: true,\n        cwd: '<%= yeoman.client %>',\n        dest: '.tmp/',\n        src: ['{app,components}/**/*.css']\n      }\n    },\n\n    buildcontrol: {\n      options: {\n        dir: 'dist',\n        commit: true,\n        push: true,\n        connectCommits: false,\n        message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'\n      },\n      heroku: {\n        options: {\n          remote: 'heroku',\n          branch: 'master'\n        }\n      },\n      openshift: {\n        options: {\n          remote: 'openshift',\n          branch: 'master'\n        }\n      }\n    },\n\n    // Run some tasks in parallel to speed up the build process\n    concurrent: {\n      server: [\n      ],\n      test: [\n      ],\n      debug: {\n        tasks: [\n          'nodemon',\n          'node-inspector'\n        ],\n        options: {\n          logConcurrentOutput: true\n        }\n      },\n      dist: [\n        'imagemin',\n        'svgmin'\n      ]\n    },\n\n    // Test settings\n    karma: {\n      unit: {\n        configFile: 'karma.conf.js',\n        singleRun: true\n      }\n    },\n\n    mochaTest: {\n      options: {\n        reporter: 'spec'\n      },\n      src: ['server/**/*.spec.js']\n    },\n\n    protractor: {\n      options: {\n        configFile: 'protractor.conf.js'\n      },\n      chrome: {\n        options: {\n          args: {\n            browser: 'chrome'\n          }\n        }\n      }\n    },\n\n    env: {\n      test: {\n        NODE_ENV: 'test'\n      },\n      prod: {\n        NODE_ENV: 'production'\n      },\n      all: localConfig\n    },\n\n    injector: {\n      options: {\n\n      },\n      // Inject application script files into index.html (doesn't include bower)\n      scripts: {\n        options: {\n          transform: function(filePath) {\n            filePath = filePath.replace('/client/', '');\n            filePath = filePath.replace('/.tmp/', '');\n            return '<script src=\"' + filePath + '\"></script>';\n          },\n          starttag: '<!-- injector:js -->',\n          endtag: '<!-- endinjector -->'\n        },\n        files: {\n          '<%= yeoman.client %>/index.html': [\n              ['{.tmp,<%= yeoman.client %>}/{app,components}/**/*.js',\n               '!{.tmp,<%= yeoman.client %>}/app/app.js',\n               '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.spec.js',\n               '!{.tmp,<%= yeoman.client %>}/{app,components}/**/*.mock.js']\n            ]\n        }\n      },\n\n      // Inject component css into index.html\n      css: {\n        options: {\n          transform: function(filePath) {\n            filePath = filePath.replace('/client/', '');\n            filePath = filePath.replace('/.tmp/', '');\n            return '<link rel=\"stylesheet\" href=\"' + filePath + '\">';\n          },\n          starttag: '<!-- injector:css -->',\n          endtag: '<!-- endinjector -->'\n        },\n        files: {\n          '<%= yeoman.client %>/index.html': [\n            '<%= yeoman.client %>/{app,components}/**/*.css'\n          ]\n        }\n      }\n    },\n  });\n\n  // Used for delaying livereload until after server has restarted\n  grunt.registerTask('wait', function () {\n    grunt.log.ok('Waiting for server reload...');\n\n    var done = this.async();\n\n    setTimeout(function () {\n      grunt.log.writeln('Done waiting!');\n      done();\n    }, 1500);\n  });\n\n  grunt.registerTask('express-keepalive', 'Keep grunt running', function() {\n    this.async();\n  });\n\n  grunt.registerTask('serve', function (target) {\n    if (target === 'dist') {\n      return grunt.task.run(['build', 'env:all', 'env:prod', 'express:prod', 'wait', 'open', 'express-keepalive']);\n    }\n\n    if (target === 'debug') {\n      return grunt.task.run([\n        'clean:server',\n        'env:all',\n        'concurrent:server',\n        'injector',\n        'wiredep',\n        'autoprefixer',\n        'concurrent:debug'\n      ]);\n    }\n\n    grunt.task.run([\n      'clean:server',\n      'env:all',\n      'concurrent:server',\n      'injector',\n      'wiredep',\n      'autoprefixer',\n      'express:dev',\n      'wait',\n      'open',\n      'watch'\n    ]);\n  });\n\n  grunt.registerTask('server', function () {\n    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');\n    grunt.task.run(['serve']);\n  });\n\n  grunt.registerTask('test', function(target) {\n    if (target === 'server') {\n      return grunt.task.run([\n        'env:all',\n        'env:test',\n        'mochaTest'\n      ]);\n    }\n\n    else if (target === 'client') {\n      return grunt.task.run([\n        'clean:server',\n        'env:all',\n        'concurrent:test',\n        'injector',\n        'autoprefixer',\n        'karma'\n      ]);\n    }\n\n    else if (target === 'e2e') {\n      return grunt.task.run([\n        'clean:server',\n        'env:all',\n        'env:test',\n        'concurrent:test',\n        'injector',\n        'wiredep',\n        'autoprefixer',\n        'express:dev',\n        'protractor'\n      ]);\n    }\n\n    else grunt.task.run([\n      'test:server',\n      'test:client'\n    ]);\n  });\n\n  grunt.registerTask('build', [\n    'clean:dist',\n    'concurrent:dist',\n    'injector',\n    'wiredep',\n    'useminPrepare',\n    'autoprefixer',\n    'ngtemplates',\n    'concat',\n    'ngAnnotate',\n    'copy:dist',\n    'cdnify',\n    'cssmin',\n    'uglify',\n    'rev',\n    'usemin'\n  ]);\n\n  grunt.registerTask('default', [\n    'newer:jshint',\n    'test',\n    'build'\n  ]);\n};\n"
  },
  {
    "path": "example/ng-route-app/README.md",
    "content": "# Stormpath Angular SDK Example\n\nThis folder contains an example application that is built with the [Stormpath Angular SDK][]\nand [Stormpath Express][].\n\nThis application is the same one that is built when you follow the [Yeoman Guide][],\nbut instead of [UI Router][], it uses the [ngRoute][] module.\n\n#### Running the Example Application\n\n1. To run this application, you will need Bower and Grunt as global packages:\n\n  ```bash\n  npm install -g grunt bower\n  ```\n\n2. Clone this repo to your computer, and enter the directory for this example:\n\n  ```bash\n  git clone https://github.com/stormpath/stormpath-sdk-angularjs.git\n  cd stormpath-sdk-angularjs/example/ng-route-app\n  ```\n\n3. Install the dependencies:\n\n  ```bash\n  npm install\n  bower install\n  ```\n4. Export your environment variables for your Stormpath Tenant and Application:\n\n  ```bash\n  export STORMPATH_CLIENT_APIKEY_ID=xxx\n  export STORMPATH_CLIENT_APIKEY_SECRET=xxx\n  export STORMPATH_APPLICATION_HREF=xxx\n  ```\n\n5. Start the server with Grunt, this should start the server and open the Angular\n  application in your browser:\n\n  ```bash\n  grunt serve\n  ```\n\n[Stormpath Angular SDK]: https://github.com/stormpath/stormpath-sdk-angularjs\n[Stormpath Express]: https://github.com/stormpath/stormpath-express\n[Yeoman Guide]: https://docs.stormpath.com/angularjs/guide\n[UI Router]: https://github.com/angular-ui/ui-router\n[ngRoute]: https://docs.angularjs.org/api/ngRoute\n"
  },
  {
    "path": "example/ng-route-app/bower.json",
    "content": "{\n  \"name\": \"dashboard\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"angular\": \">=1.2.*\",\n    \"json3\": \"~3.3.1\",\n    \"es5-shim\": \"~3.0.1\",\n    \"jquery\": \"~1.11.0\",\n    \"bootstrap\": \"~3.1.1\",\n    \"angular-route\": \"~1.4.7\",\n    \"angular-resource\": \">=1.2.*\",\n    \"angular-cookies\": \">=1.2.*\",\n    \"angular-sanitize\": \">=1.2.*\",\n    \"font-awesome\": \">=4.1.0\",\n    \"lodash\": \"~2.4.1\",\n    \"stormpath-sdk-angularjs\": \"~1.0.0\"\n  },\n  \"devDependencies\": {\n    \"angular-mocks\": \">=1.2.*\",\n    \"angular-scenario\": \">=1.2.*\"\n  }\n}\n"
  },
  {
    "path": "example/ng-route-app/client/.htaccess",
    "content": "# Apache Configuration File\n\n# (!) Using `.htaccess` files slows down Apache, therefore, if you have access\n# to the main server config file (usually called `httpd.conf`), you should add\n# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.\n\n# ##############################################################################\n# # CROSS-ORIGIN RESOURCE SHARING (CORS)                                       #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Cross-domain AJAX requests                                                 |\n# ------------------------------------------------------------------------------\n\n# Enable cross-origin AJAX requests.\n# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity\n# http://enable-cors.org/\n\n# <IfModule mod_headers.c>\n#    Header set Access-Control-Allow-Origin \"*\"\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | CORS-enabled images                                                        |\n# ------------------------------------------------------------------------------\n\n# Send the CORS header for images when browsers request it.\n# https://developer.mozilla.org/en/CORS_Enabled_Image\n# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html\n# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/\n\n<IfModule mod_setenvif.c>\n    <IfModule mod_headers.c>\n        <FilesMatch \"\\.(gif|ico|jpe?g|png|svg|svgz|webp)$\">\n            SetEnvIf Origin \":\" IS_CORS\n            Header set Access-Control-Allow-Origin \"*\" env=IS_CORS\n        </FilesMatch>\n    </IfModule>\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Web fonts access                                                           |\n# ------------------------------------------------------------------------------\n\n# Allow access from all domains for web fonts\n\n<IfModule mod_headers.c>\n    <FilesMatch \"\\.(eot|font.css|otf|ttc|ttf|woff)$\">\n        Header set Access-Control-Allow-Origin \"*\"\n    </FilesMatch>\n</IfModule>\n\n\n# ##############################################################################\n# # ERRORS                                                                     #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | 404 error prevention for non-existing redirected folders                   |\n# ------------------------------------------------------------------------------\n\n# Prevent Apache from returning a 404 error for a rewrite if a directory\n# with the same name does not exist.\n# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews\n# http://www.webmasterworld.com/apache/3808792.htm\n\nOptions -MultiViews\n\n# ------------------------------------------------------------------------------\n# | Custom error messages / pages                                              |\n# ------------------------------------------------------------------------------\n\n# You can customize what Apache returns to the client in case of an error (see\n# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:\n\nErrorDocument 404 /404.html\n\n\n# ##############################################################################\n# # INTERNET EXPLORER                                                          #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Better website experience                                                  |\n# ------------------------------------------------------------------------------\n\n# Force IE to render pages in the highest available mode in the various\n# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.\n\n<IfModule mod_headers.c>\n    Header set X-UA-Compatible \"IE=edge\"\n    # `mod_headers` can't match based on the content-type, however, we only\n    # want to send this header for HTML pages and not for the other resources\n    <FilesMatch \"\\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$\">\n        Header unset X-UA-Compatible\n    </FilesMatch>\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Cookie setting from iframes                                                |\n# ------------------------------------------------------------------------------\n\n# Allow cookies to be set from iframes in IE.\n\n# <IfModule mod_headers.c>\n#   Header set P3P \"policyref=\\\"/w3c/p3p.xml\\\", CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"\"\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | Screen flicker                                                             |\n# ------------------------------------------------------------------------------\n\n# Stop screen flicker in IE on CSS rollovers (this only works in\n# combination with the `ExpiresByType` directives for images from below).\n\n# BrowserMatch \"MSIE\" brokenvary=1\n# BrowserMatch \"Mozilla/4.[0-9]{2}\" brokenvary=1\n# BrowserMatch \"Opera\" !brokenvary\n# SetEnvIf brokenvary 1 force-no-vary\n\n\n# ##############################################################################\n# # MIME TYPES AND ENCODING                                                    #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Proper MIME types for all files                                            |\n# ------------------------------------------------------------------------------\n\n<IfModule mod_mime.c>\n\n  # Audio\n    AddType audio/mp4                                   m4a f4a f4b\n    AddType audio/ogg                                   oga ogg\n\n  # JavaScript\n    # Normalize to standard type (it's sniffed in IE anyways):\n    # http://tools.ietf.org/html/rfc4329#section-7.2\n    AddType application/javascript                      js jsonp\n    AddType application/json                            json\n\n  # Video\n    AddType video/mp4                                   mp4 m4v f4v f4p\n    AddType video/ogg                                   ogv\n    AddType video/webm                                  webm\n    AddType video/x-flv                                 flv\n\n  # Web fonts\n    AddType application/font-woff                       woff\n    AddType application/vnd.ms-fontobject               eot\n\n    # Browsers usually ignore the font MIME types and sniff the content,\n    # however, Chrome shows a warning if other MIME types are used for the\n    # following fonts.\n    AddType application/x-font-ttf                      ttc ttf\n    AddType font/opentype                               otf\n\n    # Make SVGZ fonts work on iPad:\n    # https://twitter.com/FontSquirrel/status/14855840545\n    AddType     image/svg+xml                           svg svgz\n    AddEncoding gzip                                    svgz\n\n  # Other\n    AddType application/octet-stream                    safariextz\n    AddType application/x-chrome-extension              crx\n    AddType application/x-opera-extension               oex\n    AddType application/x-shockwave-flash               swf\n    AddType application/x-web-app-manifest+json         webapp\n    AddType application/x-xpinstall                     xpi\n    AddType application/xml                             atom rdf rss xml\n    AddType image/webp                                  webp\n    AddType image/x-icon                                ico\n    AddType text/cache-manifest                         appcache manifest\n    AddType text/vtt                                    vtt\n    AddType text/x-component                            htc\n    AddType text/x-vcard                                vcf\n\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | UTF-8 encoding                                                             |\n# ------------------------------------------------------------------------------\n\n# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.\nAddDefaultCharset utf-8\n\n# Force UTF-8 for certain file formats.\n<IfModule mod_mime.c>\n    AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml\n</IfModule>\n\n\n# ##############################################################################\n# # URL REWRITES                                                               #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Rewrite engine                                                             |\n# ------------------------------------------------------------------------------\n\n# Turning on the rewrite engine and enabling the `FollowSymLinks` option is\n# necessary for the following directives to work.\n\n# If your web host doesn't allow the `FollowSymlinks` option, you may need to\n# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the\n# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks\n\n# Also, some cloud hosting services require `RewriteBase` to be set:\n# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site\n\n<IfModule mod_rewrite.c>\n    Options +FollowSymlinks\n  # Options +SymLinksIfOwnerMatch\n    RewriteEngine On\n  # RewriteBase /\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Suppressing / Forcing the \"www.\" at the beginning of URLs                  |\n# ------------------------------------------------------------------------------\n\n# The same content should never be available under two different URLs especially\n# not with and without \"www.\" at the beginning. This can cause SEO problems\n# (duplicate content), therefore, you should choose one of the alternatives and\n# redirect the other one.\n\n# By default option 1 (no \"www.\") is activated:\n# http://no-www.org/faq.php?q=class_b\n\n# If you'd prefer to use option 2, just comment out all the lines from option 1\n# and uncomment the ones from option 2.\n\n# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Option 1: rewrite www.example.com → example.com\n\n<IfModule mod_rewrite.c>\n    RewriteCond %{HTTPS} !=on\n    RewriteCond %{HTTP_HOST} ^www\\.(.+)$ [NC]\n    RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]\n</IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Option 2: rewrite example.com → www.example.com\n\n# Be aware that the following might not be a good idea if you use \"real\"\n# subdomains for certain parts of your website.\n\n# <IfModule mod_rewrite.c>\n#    RewriteCond %{HTTPS} !=on\n#    RewriteCond %{HTTP_HOST} !^www\\..+$ [NC]\n#    RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n\n# ##############################################################################\n# # SECURITY                                                                   #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Content Security Policy (CSP)                                              |\n# ------------------------------------------------------------------------------\n\n# You can mitigate the risk of cross-site scripting and other content-injection\n# attacks by setting a Content Security Policy which whitelists trusted sources\n# of content for your site.\n\n# The example header below allows ONLY scripts that are loaded from the current\n# site's origin (no inline scripts, no CDN, etc). This almost certainly won't\n# work as-is for your site!\n\n# To get all the details you'll need to craft a reasonable policy for your site,\n# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or\n# see the specification: http://w3.org/TR/CSP).\n\n# <IfModule mod_headers.c>\n#    Header set Content-Security-Policy \"script-src 'self'; object-src 'self'\"\n#    <FilesMatch \"\\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$\">\n#        Header unset Content-Security-Policy\n#    </FilesMatch>\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | File access                                                                |\n# ------------------------------------------------------------------------------\n\n# Block access to directories without a default document.\n# Usually you should leave this uncommented because you shouldn't allow anyone\n# to surf through every directory on your server (which may includes rather\n# private places like the CMS's directories).\n\n<IfModule mod_autoindex.c>\n    Options -Indexes\n</IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Block access to hidden files and directories.\n# This includes directories used by version control systems such as Git and SVN.\n\n<IfModule mod_rewrite.c>\n    RewriteCond %{SCRIPT_FILENAME} -d [OR]\n    RewriteCond %{SCRIPT_FILENAME} -f\n    RewriteRule \"(^|/)\\.\" - [F]\n</IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Block access to backup and source files.\n# These files may be left by some text editors and can pose a great security\n# danger when anyone has access to them.\n\n<FilesMatch \"(^#.*#|\\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$\">\n    Order allow,deny\n    Deny from all\n    Satisfy All\n</FilesMatch>\n\n# ------------------------------------------------------------------------------\n# | Secure Sockets Layer (SSL)                                                 |\n# ------------------------------------------------------------------------------\n\n# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:\n# prevent `https://www.example.com` when your certificate only allows\n# `https://secure.example.com`.\n\n# <IfModule mod_rewrite.c>\n#    RewriteCond %{SERVER_PORT} !^443\n#    RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n# Force client-side SSL redirection.\n\n# If a user types \"example.com\" in his browser, the above rule will redirect him\n# to the secure version of the site. That still leaves a window of opportunity\n# (the initial HTTP connection) for an attacker to downgrade or redirect the\n# request. The following header ensures that browser will ONLY connect to your\n# server via HTTPS, regardless of what the users type in the address bar.\n# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/\n\n# <IfModule mod_headers.c>\n#    Header set Strict-Transport-Security max-age=16070400;\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | Server software information                                                |\n# ------------------------------------------------------------------------------\n\n# Avoid displaying the exact Apache version number, the description of the\n# generic OS-type and the information about Apache's compiled-in modules.\n\n# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!\n\n# ServerTokens Prod\n\n\n# ##############################################################################\n# # WEB PERFORMANCE                                                            #\n# ##############################################################################\n\n# ------------------------------------------------------------------------------\n# | Compression                                                                |\n# ------------------------------------------------------------------------------\n\n<IfModule mod_deflate.c>\n\n    # Force compression for mangled headers.\n    # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping\n    <IfModule mod_setenvif.c>\n        <IfModule mod_headers.c>\n            SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\\s*,?\\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding\n            RequestHeader append Accept-Encoding \"gzip,deflate\" env=HAVE_Accept-Encoding\n        </IfModule>\n    </IfModule>\n\n    # Compress all output labeled with one of the following MIME-types\n    # (for Apache versions below 2.3.7, you don't need to enable `mod_filter`\n    #  and can remove the `<IfModule mod_filter.c>` and `</IfModule>` lines\n    #  as `AddOutputFilterByType` is still in the core directives).\n    <IfModule mod_filter.c>\n        AddOutputFilterByType DEFLATE application/atom+xml \\\n                                      application/javascript \\\n                                      application/json \\\n                                      application/rss+xml \\\n                                      application/vnd.ms-fontobject \\\n                                      application/x-font-ttf \\\n                                      application/x-web-app-manifest+json \\\n                                      application/xhtml+xml \\\n                                      application/xml \\\n                                      font/opentype \\\n                                      image/svg+xml \\\n                                      image/x-icon \\\n                                      text/css \\\n                                      text/html \\\n                                      text/plain \\\n                                      text/x-component \\\n                                      text/xml\n    </IfModule>\n\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Content transformations                                                    |\n# ------------------------------------------------------------------------------\n\n# Prevent some of the mobile network providers from modifying the content of\n# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.\n\n# <IfModule mod_headers.c>\n#    Header set Cache-Control \"no-transform\"\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | ETag removal                                                               |\n# ------------------------------------------------------------------------------\n\n# Since we're sending far-future expires headers (see below), ETags can\n# be removed: http://developer.yahoo.com/performance/rules.html#etags.\n\n# `FileETag None` is not enough for every server.\n<IfModule mod_headers.c>\n    Header unset ETag\n</IfModule>\n\nFileETag None\n\n# ------------------------------------------------------------------------------\n# | Expires headers (for better cache control)                                 |\n# ------------------------------------------------------------------------------\n\n# The following expires headers are set pretty far in the future. If you don't\n# control versioning with filename-based cache busting, consider lowering the\n# cache time for resources like CSS and JS to something like 1 week.\n\n<IfModule mod_expires.c>\n\n    ExpiresActive on\n    ExpiresDefault                                      \"access plus 1 month\"\n\n  # CSS\n    ExpiresByType text/css                              \"access plus 1 year\"\n\n  # Data interchange\n    ExpiresByType application/json                      \"access plus 0 seconds\"\n    ExpiresByType application/xml                       \"access plus 0 seconds\"\n    ExpiresByType text/xml                              \"access plus 0 seconds\"\n\n  # Favicon (cannot be renamed!)\n    ExpiresByType image/x-icon                          \"access plus 1 week\"\n\n  # HTML components (HTCs)\n    ExpiresByType text/x-component                      \"access plus 1 month\"\n\n  # HTML\n    ExpiresByType text/html                             \"access plus 0 seconds\"\n\n  # JavaScript\n    ExpiresByType application/javascript                \"access plus 1 year\"\n\n  # Manifest files\n    ExpiresByType application/x-web-app-manifest+json   \"access plus 0 seconds\"\n    ExpiresByType text/cache-manifest                   \"access plus 0 seconds\"\n\n  # Media\n    ExpiresByType audio/ogg                             \"access plus 1 month\"\n    ExpiresByType image/gif                             \"access plus 1 month\"\n    ExpiresByType image/jpeg                            \"access plus 1 month\"\n    ExpiresByType image/png                             \"access plus 1 month\"\n    ExpiresByType video/mp4                             \"access plus 1 month\"\n    ExpiresByType video/ogg                             \"access plus 1 month\"\n    ExpiresByType video/webm                            \"access plus 1 month\"\n\n  # Web feeds\n    ExpiresByType application/atom+xml                  \"access plus 1 hour\"\n    ExpiresByType application/rss+xml                   \"access plus 1 hour\"\n\n  # Web fonts\n    ExpiresByType application/font-woff                 \"access plus 1 month\"\n    ExpiresByType application/vnd.ms-fontobject         \"access plus 1 month\"\n    ExpiresByType application/x-font-ttf                \"access plus 1 month\"\n    ExpiresByType font/opentype                         \"access plus 1 month\"\n    ExpiresByType image/svg+xml                         \"access plus 1 month\"\n\n</IfModule>\n\n# ------------------------------------------------------------------------------\n# | Filename-based cache busting                                               |\n# ------------------------------------------------------------------------------\n\n# If you're not using a build process to manage your filename version revving,\n# you might want to consider enabling the following directives to route all\n# requests such as `/css/style.12345.css` to `/css/style.css`.\n\n# To understand why this is important and a better idea than `*.css?v231`, read:\n# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring\n\n# <IfModule mod_rewrite.c>\n#    RewriteCond %{REQUEST_FILENAME} !-f\n#    RewriteCond %{REQUEST_FILENAME} !-d\n#    RewriteRule ^(.+)\\.(\\d+)\\.(js|css|png|jpg|gif)$ $1.$3 [L]\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | File concatenation                                                         |\n# ------------------------------------------------------------------------------\n\n# Allow concatenation from within specific CSS and JS files, e.g.:\n# Inside of `script.combined.js` you could have\n#   <!--#include file=\"libs/jquery.js\" -->\n#   <!--#include file=\"plugins/jquery.idletimer.js\" -->\n# and they would be included into this single file.\n\n# <IfModule mod_include.c>\n#    <FilesMatch \"\\.combined\\.js$\">\n#        Options +Includes\n#        AddOutputFilterByType INCLUDES application/javascript application/json\n#        SetOutputFilter INCLUDES\n#    </FilesMatch>\n#    <FilesMatch \"\\.combined\\.css$\">\n#        Options +Includes\n#        AddOutputFilterByType INCLUDES text/css\n#        SetOutputFilter INCLUDES\n#    </FilesMatch>\n# </IfModule>\n\n# ------------------------------------------------------------------------------\n# | Persistent connections                                                     |\n# ------------------------------------------------------------------------------\n\n# Allow multiple requests to be sent over the same TCP connection:\n# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.\n\n# Enable if you serve a lot of static content but, be aware of the\n# possible disadvantages!\n\n# <IfModule mod_headers.c>\n#    Header set Connection Keep-Alive\n# </IfModule>\n"
  },
  {
    "path": "example/ng-route-app/client/.jshintrc",
    "content": "{\n  \"node\": true,\n  \"browser\": true,\n  \"esnext\": true,\n  \"bitwise\": true,\n  \"camelcase\": true,\n  \"curly\": true,\n  \"eqeqeq\": true,\n  \"immed\": true,\n  \"indent\": 2,\n  \"latedef\": true,\n  \"newcap\": true,\n  \"noarg\": true,\n  \"quotmark\": \"single\",\n  \"regexp\": true,\n  \"undef\": true,\n  \"unused\": true,\n  \"strict\": true,\n  \"trailing\": true,\n  \"smarttabs\": true,\n  \"globals\": {\n    \"jQuery\": true,\n    \"angular\": true,\n    \"console\": true,\n    \"$\": true,\n    \"_\": true,\n    \"moment\": true,\n    \"describe\": true,\n    \"beforeEach\": true,\n    \"module\": true,\n    \"inject\": true,\n    \"it\": true,\n    \"expect\": true,\n    \"browser\": true,\n    \"element\": true,\n    \"by\": true\n  }\n}\n"
  },
  {
    "path": "example/ng-route-app/client/app/app.css",
    "content": "\n/**\n * Bootstrap Fonts\n */\n\n@font-face {\n    font-family: 'Glyphicons Halflings';\n    src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot');\n    src: url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),\n    url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff') format('woff'),\n    url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf') format('truetype'),\n    url('../bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n\n/**\n *Font Awesome Fonts\n */\n\n@font-face {\n    font-family: 'FontAwesome';\n    src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?v=4.1.0');\n    src: url('../bower_components/font-awesome/fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),\n    url('../bower_components/font-awesome/fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),\n    url('../bower_components/font-awesome/fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),\n    url('../bower_components/font-awesome/fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');\n    font-weight: normal;\n    font-style: normal;\n}\n\n/**\n * App-wide Styles\n */\n\n.browsehappy {\n    margin: 0.2em 0;\n    background: #ccc;\n    color: #000;\n    padding: 0.2em 0;\n}\n"
  },
  {
    "path": "example/ng-route-app/client/app/app.js",
    "content": "'use strict';\n\nangular.module('dashboardApp', [\n  'ngCookies',\n  'ngResource',\n  'ngSanitize',\n  'ngRoute',\n  'stormpath',\n  'stormpath.templates'\n])\n  .config(function ($routeProvider, $locationProvider) {\n    $routeProvider.otherwise('/');\n    $locationProvider.html5Mode(true);\n  })\n  .run(function($stormpath, $rootScope, $location) {\n    $stormpath.ngRouter({\n      loginRoute: '/login',\n      defaultPostLoginRoute: '/'\n    });\n\n    $rootScope.$on('$sessionEnd', function() {\n      $location.path('/login');\n    });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/forgot/forgot.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('ForgotCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/forgot/forgot.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: ForgotCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var ForgotCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    ForgotCtrl = $controller('ForgotCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/forgot/forgot.css",
    "content": ""
  },
  {
    "path": "example/ng-route-app/client/app/forgot/forgot.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Forgot Password</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-password-reset-request-form></div>\n</div>"
  },
  {
    "path": "example/ng-route-app/client/app/forgot/forgot.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/forgot', {\n        templateUrl: 'app/forgot/forgot.html',\n        controller: 'ForgotCtrl'\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/login/login.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('LoginCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/login/login.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: LoginCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var LoginCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    LoginCtrl = $controller('LoginCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/login/login.css",
    "content": ""
  },
  {
    "path": "example/ng-route-app/client/app/login/login.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Login</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-login-form></div>\n</div>"
  },
  {
    "path": "example/ng-route-app/client/app/login/login.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/login', {\n        templateUrl: 'app/login/login.html',\n        controller: 'LoginCtrl'\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/main/main.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('MainCtrl', function ($scope, $http) {\n    $scope.awesomeThings = [];\n\n    $http.get('/api/things').success(function(awesomeThings) {\n      $scope.awesomeThings = awesomeThings;\n    });\n\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/main/main.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: MainCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var MainCtrl,\n      scope,\n      $httpBackend;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function (_$httpBackend_, $controller, $rootScope) {\n    $httpBackend = _$httpBackend_;\n    $httpBackend.expectGET('/api/things')\n      .respond(['HTML5 Boilerplate', 'AngularJS', 'Karma', 'Express']);\n\n    scope = $rootScope.$new();\n    MainCtrl = $controller('MainCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should attach a list of things to the scope', function () {\n    $httpBackend.flush();\n    expect(scope.awesomeThings.length).toBe(4);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/main/main.css",
    "content": ".thing-form {\n    margin: 20px 0;\n}\n\n#banner {\n    border-bottom: none;\n    margin-top: -20px;\n}\n\n#banner h1 {\n    font-size: 60px;\n    line-height: 1;\n    letter-spacing: -1px;\n}\n\n.hero-unit {\n    position: relative;\n    padding: 30px 15px;\n    color: #F5F5F5;\n    text-align: center;\n    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);\n    background: #4393B9;\n}\n\n.footer {\n    text-align: center;\n    padding: 30px 0;\n    margin-top: 70px;\n    border-top: 1px solid #E5E5E5;\n}"
  },
  {
    "path": "example/ng-route-app/client/app/main/main.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<header class=\"hero-unit\" id=\"banner\">\n  <div class=\"container\">\n    <h1>'Allo, 'Allo!</h1>\n    <p class=\"lead\">Kick-start your next web app with Angular Fullstack</p>\n    <img src=\"assets/images/yeoman.png\" alt=\"I'm Yeoman\">\n  </div>\n</header>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-lg-12\">\n      <h1 class=\"page-header\">Features:</h1>\n      <ul class=\"nav nav-tabs nav-stacked col-md-4 col-lg-4 col-sm-6\" ng-repeat=\"thing in awesomeThings\">\n        <li><a href=\"#\" tooltip=\"{{thing.info}}\">{{thing.name}}</a></li>\n      </ul>\n    </div>\n  </div>\n</div>\n\n<footer class=\"footer\">\n  <div class=\"container\">\n      <p>Angular Fullstack v2.0.13 |\n        <a href=\"https://twitter.com/tyhenkel\">@tyhenkel</a> |\n         <a href=\"https://github.com/DaftMonk/generator-angular-fullstack/issues?state=open\">Issues</a></p>\n  </div>\n</footer>\n"
  },
  {
    "path": "example/ng-route-app/client/app/main/main.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/', {\n        templateUrl: 'app/main/main.html',\n        controller: 'MainCtrl'\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/profile/profile.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('ProfileCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/profile/profile.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: ProfileCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var ProfileCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    ProfileCtrl = $controller('ProfileCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/profile/profile.css",
    "content": ""
  },
  {
    "path": "example/ng-route-app/client/app/profile/profile.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>My Profile</h3>\n      <hr>\n    </div>\n\n  </div>\n\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <pre ng-bind=\"user | json\"></pre>\n    </div>\n  </div>\n</div>"
  },
  {
    "path": "example/ng-route-app/client/app/profile/profile.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/profile', {\n        templateUrl: 'app/profile/profile.html',\n        controller: 'ProfileCtrl',\n        sp: {\n          authenticate: true\n        }\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/register/register.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('RegisterCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/register/register.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: RegisterCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var RegisterCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    RegisterCtrl = $controller('RegisterCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/register/register.css",
    "content": ""
  },
  {
    "path": "example/ng-route-app/client/app/register/register.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Registration</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-registration-form post-login-state=\"main\"></div>\n</div>"
  },
  {
    "path": "example/ng-route-app/client/app/register/register.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/register', {\n        templateUrl: 'app/register/register.html',\n        controller: 'RegisterCtrl'\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/reset/reset.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('ResetCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/reset/reset.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: ResetCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var ResetCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    ResetCtrl = $controller('ResetCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/reset/reset.css",
    "content": ""
  },
  {
    "path": "example/ng-route-app/client/app/reset/reset.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Reset Your Password</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-password-reset-form></div>\n</div>"
  },
  {
    "path": "example/ng-route-app/client/app/reset/reset.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/reset', {\n        templateUrl: 'app/reset/reset.html',\n        controller: 'ResetCtrl'\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/app/verify/verify.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('VerifyCtrl', function ($scope) {\n    $scope.message = 'Hello';\n  });\n"
  },
  {
    "path": "example/ng-route-app/client/app/verify/verify.controller.spec.js",
    "content": "'use strict';\n\ndescribe('Controller: VerifyCtrl', function () {\n\n  // load the controller's module\n  beforeEach(module('dashboardApp'));\n\n  var VerifyCtrl, scope;\n\n  // Initialize the controller and a mock scope\n  beforeEach(inject(function ($controller, $rootScope) {\n    scope = $rootScope.$new();\n    VerifyCtrl = $controller('VerifyCtrl', {\n      $scope: scope\n    });\n  }));\n\n  it('should ...', function () {\n    expect(1).toEqual(1);\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/client/app/verify/verify.css",
    "content": ""
  },
  {
    "path": "example/ng-route-app/client/app/verify/verify.html",
    "content": "<div ng-include=\"'components/navbar/navbar.html'\"></div>\n\n<div class=\"container\">\n  <div class=\"row\">\n    <div class=\"col-xs-12\">\n      <h3>Verify Your Account</h3>\n      <hr>\n    </div>\n  </div>\n  <div sp-email-verification></div>\n</div>"
  },
  {
    "path": "example/ng-route-app/client/app/verify/verify.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .config(function ($routeProvider) {\n    $routeProvider\n      .when('/verify', {\n        templateUrl: 'app/verify/verify.html',\n        controller: 'VerifyCtrl'\n      });\n  });"
  },
  {
    "path": "example/ng-route-app/client/components/navbar/navbar.controller.js",
    "content": "'use strict';\n\nangular.module('dashboardApp')\n  .controller('NavbarCtrl', function ($scope, $location) {\n    $scope.menu = [{\n      'title': 'Home',\n      'link': '/'\n    }];\n\n    $scope.isCollapsed = true;\n\n    $scope.isActive = function(route) {\n      return route === $location.path();\n    };\n  });"
  },
  {
    "path": "example/ng-route-app/client/components/navbar/navbar.html",
    "content": "<div class=\"navbar navbar-default navbar-static-top\" ng-controller=\"NavbarCtrl\">\n  <div class=\"container\">\n    <div class=\"navbar-header\">\n      <button class=\"navbar-toggle\" type=\"button\" ng-click=\"isCollapsed = !isCollapsed\">\n        <span class=\"sr-only\">Toggle navigation</span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n      </button>\n      <a href=\"/\" class=\"navbar-brand\">dashboard</a>\n    </div>\n    <div collapse=\"isCollapsed\" class=\"navbar-collapse collapse\" id=\"navbar-main\">\n      <ul class=\"nav navbar-nav\">\n        <li ng-repeat=\"item in menu\" ng-class=\"{active: isActive(item.link)}\">\n            <a ng-href=\"{{item.link}}\">{{item.title}}</a>\n        </li>\n        <li if-user ng-class=\"{active: isActive('/profile')}\">\n            <a href=\"/profile\">Profile</a>\n        </li>\n        <li if-not-user ng-class=\"{active: isActive('/register')}\">\n            <a href=\"/register\">Register</a>\n        </li>\n        <li if-not-user ng-class=\"{active: isActive('/login')}\">\n            <a href=\"/login\">Login</a>\n        </li>\n        <li if-user ng-class=\"{active: isActive('/logout')}\">\n            <a href=\"/\" sp-logout>Logout</a>\n        </li>\n      </ul>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "example/ng-route-app/client/index.html",
    "content": "<!doctype html>\n<!--[if lt IE 7]>      <html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"> <![endif]-->\n<!--[if IE 7]>         <html class=\"no-js lt-ie9 lt-ie8\"> <![endif]-->\n<!--[if IE 8]>         <html class=\"no-js lt-ie9\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js\"> <!--<![endif]-->\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <base href=\"/\">\n    <title></title>\n    <meta name=\"description\" content=\"\">\n    <meta name=\"viewport\" content=\"width=device-width\">\n    <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->\n    <!-- build:css(client) app/vendor.css -->\n      <!-- bower:css -->\n      <link rel=\"stylesheet\" href=\"bower_components/bootstrap/dist/css/bootstrap.css\" />\n      <!-- endbower -->\n    <!-- endbuild -->\n    <!-- build:css({.tmp,client}) app/app.css -->\n    <link rel=\"stylesheet\" href=\"app/app.css\">\n      <!-- injector:css -->\n      <link rel=\"stylesheet\" href=\"app/app.css\">\n      <link rel=\"stylesheet\" href=\"app/forgot/forgot.css\">\n      <link rel=\"stylesheet\" href=\"app/login/login.css\">\n      <link rel=\"stylesheet\" href=\"app/main/main.css\">\n      <link rel=\"stylesheet\" href=\"app/profile/profile.css\">\n      <link rel=\"stylesheet\" href=\"app/register/register.css\">\n      <link rel=\"stylesheet\" href=\"app/reset/reset.css\">\n      <link rel=\"stylesheet\" href=\"app/verify/verify.css\">\n      <!-- endinjector -->\n    <!-- endbuild -->\n  </head>\n  <body ng-app=\"dashboardApp\">\n    <!--[if lt IE 7]>\n      <p class=\"browsehappy\">You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/\">upgrade your browser</a> to improve your experience.</p>\n    <![endif]-->\n\n    <!-- Add your site or application content here -->\n    <div ng-view></div>\n\n    <!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->\n    <script>\n      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n      (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n      m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n      ga('create', 'UA-XXXXX-X');\n      ga('send', 'pageview');\n    </script>\n\n    <!--[if lt IE 9]>\n    <script src=\"bower_components/es5-shim/es5-shim.js\"></script>\n    <script src=\"bower_components/json3/lib/json3.min.js\"></script>\n    <![endif]-->\n    <!-- build:js({client,node_modules}) app/vendor.js -->\n      <!-- bower:js -->\n      <script src=\"bower_components/jquery/dist/jquery.js\"></script>\n      <script src=\"bower_components/angular/angular.js\"></script>\n      <script src=\"bower_components/angular-route/angular-route.js\"></script>\n      <script src=\"bower_components/angular-resource/angular-resource.js\"></script>\n      <script src=\"bower_components/angular-cookies/angular-cookies.js\"></script>\n      <script src=\"bower_components/angular-sanitize/angular-sanitize.js\"></script>\n      <script src=\"bower_components/lodash/dist/lodash.compat.js\"></script>\n      <script src=\"bower_components/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.min.js\"></script>\n      <script src=\"bower_components/stormpath-sdk-angularjs/dist/stormpath-sdk-angularjs.tpls.min.js\"></script>\n      <!-- endbower -->\n    <!-- endbuild -->\n\n        <!-- build:js({.tmp,client}) app/app.js -->\n        <script src=\"app/app.js\"></script>\n          <!-- injector:js -->\n          <script src=\"app/forgot/forgot.controller.js\"></script>\n          <script src=\"app/forgot/forgot.js\"></script>\n          <script src=\"app/login/login.controller.js\"></script>\n          <script src=\"app/login/login.js\"></script>\n          <script src=\"app/main/main.controller.js\"></script>\n          <script src=\"app/main/main.js\"></script>\n          <script src=\"app/profile/profile.controller.js\"></script>\n          <script src=\"app/profile/profile.js\"></script>\n          <script src=\"app/register/register.controller.js\"></script>\n          <script src=\"app/register/register.js\"></script>\n          <script src=\"app/reset/reset.controller.js\"></script>\n          <script src=\"app/reset/reset.js\"></script>\n          <script src=\"app/verify/verify.controller.js\"></script>\n          <script src=\"app/verify/verify.js\"></script>\n          <script src=\"components/navbar/navbar.controller.js\"></script>\n          <!-- endinjector -->\n        <!-- endbuild -->\n</body>\n</html>\n"
  },
  {
    "path": "example/ng-route-app/client/robots.txt",
    "content": "# robotstxt.org\n\nUser-agent: *\n"
  },
  {
    "path": "example/ng-route-app/e2e/main/main.po.js",
    "content": "/**\n * This file uses the Page Object pattern to define the main page for tests\n * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ\n */\n\n'use strict';\n\nvar MainPage = function() {\n  this.heroEl = element(by.css('.hero-unit'));\n  this.h1El = this.heroEl.element(by.css('h1'));\n  this.imgEl = this.heroEl.element(by.css('img'));\n};\n\nmodule.exports = new MainPage();\n\n"
  },
  {
    "path": "example/ng-route-app/e2e/main/main.spec.js",
    "content": "'use strict';\n\ndescribe('Main View', function() {\n  var page;\n\n  beforeEach(function() {\n    browser.get('/');\n    page = require('./main.po');\n  });\n\n  it('should include jumbotron with correct data', function() {\n    expect(page.h1El.getText()).toBe('\\'Allo, \\'Allo!');\n    expect(page.imgEl.getAttribute('src')).toMatch(/assets\\/images\\/yeoman.png$/);\n    expect(page.imgEl.getAttribute('alt')).toBe('I\\'m Yeoman');\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/karma.conf.js",
    "content": "// Karma configuration\n// http://karma-runner.github.io/0.10/config/configuration-file.html\n\nmodule.exports = function(config) {\n  config.set({\n    // base path, that will be used to resolve files and exclude\n    basePath: '',\n\n    // testing framework to use (jasmine/mocha/qunit/...)\n    frameworks: ['jasmine'],\n\n    // list of files / patterns to load in the browser\n    files: [\n      'client/bower_components/jquery/dist/jquery.js',\n      'client/bower_components/angular/angular.js',\n      'client/bower_components/angular-mocks/angular-mocks.js',\n      'client/bower_components/angular-resource/angular-resource.js',\n      'client/bower_components/angular-cookies/angular-cookies.js',\n      'client/bower_components/angular-sanitize/angular-sanitize.js',\n      'client/bower_components/angular-route/angular-route.js',\n      'client/bower_components/lodash/dist/lodash.compat.js',\n      'client/bower_components/angular-ui-router/release/angular-ui-router.js',\n      'client/app/app.js',\n      'client/app/app.coffee',\n      'client/app/**/*.js',\n      'client/app/**/*.coffee',\n      'client/components/**/*.js',\n      'client/components/**/*.coffee',\n      'client/app/**/*.jade',\n      'client/components/**/*.jade',\n      'client/app/**/*.html',\n      'client/components/**/*.html'\n    ],\n\n    preprocessors: {\n      '**/*.jade': 'ng-jade2js',\n      '**/*.html': 'html2js',\n      '**/*.coffee': 'coffee',\n    },\n\n    ngHtml2JsPreprocessor: {\n      stripPrefix: 'client/'\n    },\n\n    ngJade2JsPreprocessor: {\n      stripPrefix: 'client/'\n    },\n\n    // list of files / patterns to exclude\n    exclude: [],\n\n    // web server port\n    port: 8080,\n\n    // level of logging\n    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG\n    logLevel: config.LOG_INFO,\n\n\n    // enable / disable watching file and executing tests whenever any file changes\n    autoWatch: false,\n\n\n    // Start these browsers, currently available:\n    // - Chrome\n    // - ChromeCanary\n    // - Firefox\n    // - Opera\n    // - Safari (only Mac)\n    // - PhantomJS\n    // - IE (only Windows)\n    browsers: ['PhantomJS'],\n\n\n    // Continuous Integration mode\n    // if true, it capture browsers, run tests and exit\n    singleRun: false\n  });\n};\n"
  },
  {
    "path": "example/ng-route-app/package.json",
    "content": "{\n  \"name\": \"dashboard\",\n  \"version\": \"0.0.0\",\n  \"main\": \"server/app.js\",\n  \"dependencies\": {\n    \"body-parser\": \"~1.5.0\",\n    \"composable-middleware\": \"^0.3.0\",\n    \"compression\": \"~1.0.1\",\n    \"connect-mongo\": \"^0.4.1\",\n    \"cookie-parser\": \"~1.0.1\",\n    \"ejs\": \"~0.8.4\",\n    \"errorhandler\": \"~1.0.0\",\n    \"express\": \"^4.13.3\",\n    \"express-session\": \"~1.0.2\",\n    \"express-stormpath\": \"^3.0.0\",\n    \"lodash\": \"~2.4.1\",\n    \"method-override\": \"~1.0.0\",\n    \"morgan\": \"~1.0.0\",\n    \"serve-favicon\": \"~2.0.1\"\n  },\n  \"devDependencies\": {\n    \"grunt\": \"~0.4.4\",\n    \"grunt-autoprefixer\": \"~0.7.2\",\n    \"grunt-wiredep\": \"~1.8.0\",\n    \"grunt-concurrent\": \"~0.5.0\",\n    \"grunt-contrib-clean\": \"~0.5.0\",\n    \"grunt-contrib-concat\": \"~0.4.0\",\n    \"grunt-contrib-copy\": \"~0.5.0\",\n    \"grunt-contrib-cssmin\": \"~0.9.0\",\n    \"grunt-contrib-htmlmin\": \"~0.2.0\",\n    \"grunt-contrib-imagemin\": \"~0.7.1\",\n    \"grunt-contrib-jshint\": \"~0.10.0\",\n    \"grunt-contrib-uglify\": \"~0.4.0\",\n    \"grunt-contrib-watch\": \"~0.6.1\",\n    \"grunt-google-cdn\": \"~0.4.0\",\n    \"grunt-newer\": \"~0.7.0\",\n    \"grunt-ng-annotate\": \"^0.2.3\",\n    \"grunt-rev\": \"~0.1.0\",\n    \"grunt-svgmin\": \"~0.4.0\",\n    \"grunt-usemin\": \"~2.1.1\",\n    \"grunt-env\": \"~0.4.1\",\n    \"grunt-node-inspector\": \"~0.1.5\",\n    \"grunt-nodemon\": \"~0.2.0\",\n    \"grunt-angular-templates\": \"^0.5.4\",\n    \"grunt-dom-munger\": \"^3.4.0\",\n    \"grunt-protractor-runner\": \"^1.1.0\",\n    \"grunt-asset-injector\": \"^0.1.0\",\n    \"grunt-karma\": \"~0.8.2\",\n    \"grunt-build-control\": \"DaftMonk/grunt-build-control\",\n    \"grunt-mocha-test\": \"~0.10.2\",\n    \"jit-grunt\": \"^0.5.0\",\n    \"time-grunt\": \"~0.3.1\",\n    \"grunt-express-server\": \"~0.4.17\",\n    \"grunt-open\": \"~0.2.3\",\n    \"open\": \"~0.0.4\",\n    \"jshint-stylish\": \"~0.1.5\",\n    \"connect-livereload\": \"~0.4.0\",\n    \"karma-ng-scenario\": \"~0.1.0\",\n    \"karma-firefox-launcher\": \"~0.1.3\",\n    \"karma-script-launcher\": \"~0.1.0\",\n    \"karma-html2js-preprocessor\": \"~0.1.0\",\n    \"karma-ng-jade2js-preprocessor\": \"^0.1.2\",\n    \"karma-jasmine\": \"~0.1.5\",\n    \"karma-chrome-launcher\": \"~0.1.3\",\n    \"requirejs\": \"~2.1.11\",\n    \"karma-requirejs\": \"~0.2.1\",\n    \"karma-coffee-preprocessor\": \"~0.2.1\",\n    \"karma-jade-preprocessor\": \"0.0.11\",\n    \"karma-phantomjs-launcher\": \"~0.1.4\",\n    \"karma\": \"~0.12.9\",\n    \"karma-ng-html2js-preprocessor\": \"~0.1.0\",\n    \"supertest\": \"~0.11.0\",\n    \"should\": \"~3.3.1\"\n  },\n  \"engines\": {\n    \"node\": \">=0.10.0\"\n  },\n  \"scripts\": {\n    \"start\": \"node server/app.js\",\n    \"test\": \"grunt test\",\n    \"update-webdriver\": \"node node_modules/grunt-protractor-runner/node_modules/protractor/bin/webdriver-manager update\"\n  },\n  \"private\": true\n}\n"
  },
  {
    "path": "example/ng-route-app/protractor.conf.js",
    "content": "// Protractor configuration\n// https://github.com/angular/protractor/blob/master/referenceConf.js\n\n'use strict';\n\nexports.config = {\n  // The timeout for each script run on the browser. This should be longer\n  // than the maximum time your application needs to stabilize between tasks.\n  allScriptsTimeout: 110000,\n\n  // A base URL for your application under test. Calls to protractor.get()\n  // with relative paths will be prepended with this.\n  baseUrl: 'http://localhost:' + (process.env.PORT || '9000'),\n\n  // If true, only chromedriver will be started, not a standalone selenium.\n  // Tests for browsers other than chrome will not run.\n  chromeOnly: true,\n\n  // list of files / patterns to load in the browser\n  specs: [\n    'e2e/**/*.spec.js'\n  ],\n\n  // Patterns to exclude.\n  exclude: [],\n\n  // ----- Capabilities to be passed to the webdriver instance ----\n  //\n  // For a full list of available capabilities, see\n  // https://code.google.com/p/selenium/wiki/DesiredCapabilities\n  // and\n  // https://code.google.com/p/selenium/source/browse/javascript/webdriver/capabilities.js\n  capabilities: {\n    'browserName': 'chrome'\n  },\n\n  // ----- The test framework -----\n  //\n  // Jasmine and Cucumber are fully supported as a test and assertion framework.\n  // Mocha has limited beta support. You will need to include your own\n  // assertion framework if working with mocha.\n  framework: 'jasmine',\n\n  // ----- Options to be passed to minijasminenode -----\n  //\n  // See the full list at https://github.com/juliemr/minijasminenode\n  jasmineNodeOpts: {\n    defaultTimeoutInterval: 30000\n  }\n};\n"
  },
  {
    "path": "example/ng-route-app/server/.jshintrc",
    "content": "{\n  \"node\": true,\n  \"esnext\": true,\n  \"bitwise\": true,\n  \"eqeqeq\": true,\n  \"immed\": true,\n  \"latedef\": \"nofunc\",\n  \"newcap\": true,\n  \"noarg\": true,\n  \"regexp\": true,\n  \"undef\": true,\n  \"smarttabs\": true,\n  \"asi\": true,\n  \"debug\": true\n}\n"
  },
  {
    "path": "example/ng-route-app/server/.jshintrc-spec",
    "content": "{\n  \"extends\": \".jshintrc\",\n  \"globals\": {\n    \"describe\": true,\n    \"it\": true,\n    \"before\": true,\n    \"beforeEach\": true,\n    \"after\": true,\n    \"afterEach\": true\n  }\n}\n"
  },
  {
    "path": "example/ng-route-app/server/api/thing/index.js",
    "content": "'use strict';\n\nvar express = require('express');\nvar controller = require('./thing.controller');\n\nvar router = express.Router();\n\nrouter.get('/', controller.index);\n\nmodule.exports = router;"
  },
  {
    "path": "example/ng-route-app/server/api/thing/thing.controller.js",
    "content": "/**\n * Using Rails-like standard naming convention for endpoints.\n * GET     /things              ->  index\n * POST    /things              ->  create\n * GET     /things/:id          ->  show\n * PUT     /things/:id          ->  update\n * DELETE  /things/:id          ->  destroy\n */\n\n'use strict';\n\nvar _ = require('lodash');\n\n// Get list of things\nexports.index = function(req, res) {\n  res.json([\n  {\n  name : 'Development Tools',\n  info : 'Integration with popular tools such as Bower, Grunt, Karma, Mocha, JSHint, Node Inspector, Livereload, Protractor, Jade, Stylus, Sass, CoffeeScript, and Less.'\n  }, {\n  name : 'Server and Client integration',\n  info : 'Built with a powerful and fun stack: MongoDB, Express, AngularJS, and Node.'\n  }, {\n  name : 'Smart Build System',\n  info : 'Build system ignores `spec` files, allowing you to keep tests alongside code. Automatic injection of scripts and styles into your index.html'\n  },  {\n  name : 'Modular Structure',\n  info : 'Best practice client and server structures allow for more code reusability and maximum scalability'\n  },  {\n  name : 'Optimized Build',\n  info : 'Build process packs up your templates as a single JavaScript payload, minifies your scripts/css/images, and rewrites asset names for caching.'\n  },{\n  name : 'Deployment Ready',\n  info : 'Easily deploy your app to Heroku or Openshift with the heroku and openshift subgenerators'\n  }\n  ]);\n};"
  },
  {
    "path": "example/ng-route-app/server/api/thing/thing.spec.js",
    "content": "'use strict';\n\nvar should = require('should');\nvar app = require('../../app');\nvar request = require('supertest');\n\ndescribe('GET /api/things', function() {\n\n  it('should respond with JSON array', function(done) {\n    request(app)\n      .get('/api/things')\n      .expect(200)\n      .expect('Content-Type', /json/)\n      .end(function(err, res) {\n        if (err) return done(err);\n        res.body.should.be.instanceof(Array);\n        done();\n      });\n  });\n});\n"
  },
  {
    "path": "example/ng-route-app/server/app.js",
    "content": "/**\n * Main application file\n */\n\n'use strict';\n\n// Set default node environment to development\nprocess.env.NODE_ENV = process.env.NODE_ENV || 'development';\n\nvar express = require('express');\nvar config = require('./config/environment');\nvar ExpressStormpath = require('express-stormpath');\n\n// Setup server\nvar app = express();\n\nvar server = require('http').createServer(app);\n\n/*\n  The config/express file is setting up the static file server which serves your\n  angular application assets.  We don't need to authenticate those requests, so\n  we do this before calling Stormpath.\n */\n\nrequire('./config/express')(app);\n\nconsole.log('Initializing Stormpath');\n\n/*\n  Now we initialize Stormpath, any middleware that is registered after this\n  point will be protected by Stormpath.\n\n  The spaRoot setting tells the Stormpath library where your Angular app is,\n  as it will need to serve it for the default routes like /login and\n  /register.  The appPath property is provided by the configuration parser\n  in the Yeoman boilerplate.\n */\n\napp.use(ExpressStormpath.init(app,{\n  web: {\n    produces: ['application/json'],\n    spa: {\n      enabled: true,\n      view: app.get('appPath')\n    }\n  }\n}));\n\n\nrequire('./routes')(app);\n\napp.on('stormpath.ready',function() {\n  console.log('Stormpath Ready');\n});\n\n// Start server\nserver.listen(config.port, config.ip, function () {\n  console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));\n});\n\n\n// Expose app\nexports = module.exports = app;\n\n"
  },
  {
    "path": "example/ng-route-app/server/components/errors/index.js",
    "content": "/**\n * Error responses\n */\n\n'use strict';\n\nmodule.exports[404] = function pageNotFound(req, res) {\n  var viewFilePath = '404';\n  var statusCode = 404;\n  var result = {\n    status: statusCode\n  };\n\n  res.status(result.status);\n  res.render(viewFilePath, function (err) {\n    if (err) { return res.json(result, result.status); }\n\n    res.render(viewFilePath);\n  });\n};\n"
  },
  {
    "path": "example/ng-route-app/server/config/environment/development.js",
    "content": "'use strict';\n\n// Development specific configuration\n// ==================================\nmodule.exports = {\n  // MongoDB connection options\n  mongo: {\n    uri: 'mongodb://localhost/dashboard-dev'\n  },\n\n  seedDB: true\n};\n"
  },
  {
    "path": "example/ng-route-app/server/config/environment/index.js",
    "content": "'use strict';\n\nvar path = require('path');\nvar _ = require('lodash');\n\nfunction requiredProcessEnv(name) {\n  if(!process.env[name]) {\n    throw new Error('You must set the ' + name + ' environment variable');\n  }\n  return process.env[name];\n}\n\n// All configurations will extend these options\n// ============================================\nvar all = {\n  env: process.env.NODE_ENV,\n\n  // Root path of server\n  root: path.normalize(__dirname + '/../../..'),\n\n  // Server port\n  port: process.env.PORT || 9000,\n\n  // Should we populate the DB with sample data?\n  seedDB: false,\n\n  // Secret for session, you will want to change this and make it an environment variable\n  secrets: {\n    session: 'dashboard-secret'\n  },\n\n  // List of user roles\n  userRoles: ['guest', 'user', 'admin'],\n\n  // MongoDB connection options\n  mongo: {\n    options: {\n      db: {\n        safe: true\n      }\n    }\n  },\n\n};\n\n// Export the config object based on the NODE_ENV\n// ==============================================\nmodule.exports = _.merge(\n  all,\n  require('./' + process.env.NODE_ENV + '.js') || {});"
  },
  {
    "path": "example/ng-route-app/server/config/environment/production.js",
    "content": "'use strict';\n\n// Production specific configuration\n// =================================\nmodule.exports = {\n  // Server IP\n  ip:       process.env.OPENSHIFT_NODEJS_IP ||\n            process.env.IP ||\n            undefined,\n\n  // Server port\n  port:     process.env.OPENSHIFT_NODEJS_PORT ||\n            process.env.PORT ||\n            8080,\n\n  // MongoDB connection options\n  mongo: {\n    uri:    process.env.MONGOLAB_URI ||\n            process.env.MONGOHQ_URL ||\n            process.env.OPENSHIFT_MONGODB_DB_URL+process.env.OPENSHIFT_APP_NAME ||\n            'mongodb://localhost/dashboard'\n  }\n};"
  },
  {
    "path": "example/ng-route-app/server/config/environment/test.js",
    "content": "'use strict';\n\n// Test specific configuration\n// ===========================\nmodule.exports = {\n  // MongoDB connection options\n  mongo: {\n    uri: 'mongodb://localhost/dashboard-test'\n  }\n};"
  },
  {
    "path": "example/ng-route-app/server/config/express.js",
    "content": "/**\n * Express configuration\n */\n\n'use strict';\n\nvar express = require('express');\nvar favicon = require('serve-favicon');\nvar morgan = require('morgan');\nvar compression = require('compression');\nvar bodyParser = require('body-parser');\nvar methodOverride = require('method-override');\nvar cookieParser = require('cookie-parser');\nvar errorHandler = require('errorhandler');\nvar path = require('path');\nvar config = require('./environment');\n\nmodule.exports = function(app) {\n  var env = app.get('env');\n\n  app.set('views', config.root + '/server/views');\n  app.engine('html', require('ejs').renderFile);\n  app.set('view engine', 'html');\n  app.set('trust proxy', true);\n  app.use(compression());\n  app.use(methodOverride());\n  app.use(cookieParser());\n\n  if ('production' === env) {\n    app.use(favicon(path.join(config.root, 'public', 'favicon.ico')));\n    app.use(express.static(path.join(config.root, 'public')));\n    app.set('appPath', path.join(config.root, 'public', 'index.html'));\n    app.use(morgan('dev'));\n  }\n\n  if ('development' === env || 'test' === env) {\n    app.use(require('connect-livereload')());\n    app.use(express.static(path.join(config.root, '.tmp')));\n    app.use(express.static(path.join(config.root, 'client')));\n    app.set('appPath', path.join(config.root, 'client', 'index.html'));\n    app.use(morgan('dev'));\n    app.use(errorHandler()); // Error handler - has to be last\n  }\n};\n\n"
  },
  {
    "path": "example/ng-route-app/server/config/local.env.sample.js",
    "content": "'use strict';\n\n// Use local.env.js for environment variables that grunt will set when the server starts locally.\n// Use for your api keys, secrets, etc. This file should not be tracked by git.\n//\n// You will need to set these on the server you deploy to.\n\nmodule.exports = {\n  DOMAIN:           'http://localhost:9000',\n  SESSION_SECRET:   'dashboard-secret',\n\n  // Control debug level for modules using visionmedia/debug\n  DEBUG: ''\n};\n"
  },
  {
    "path": "example/ng-route-app/server/routes.js",
    "content": "/**\n * Main application routes\n */\n\n'use strict';\n\nvar errors = require('./components/errors');\nvar ExpressStormpath = require('express-stormpath');\n\nmodule.exports = function(app) {\n\n  // Insert routes below\n  app.use('/api/things', ExpressStormpath.loginRequired, require('./api/thing'));\n\n  // All undefined asset or api routes should return a 404\n  app.route('/:url(api|auth|components|app|bower_components|assets)/*')\n   .get(errors[404]);\n\n  // All other routes should redirect to the index.html\n  app.route('/*')\n    .get(function(req, res) {\n      res.sendFile(app.get('appPath'));\n    });\n};\n"
  },
  {
    "path": "example/ng-route-app/server/views/404.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Page Not Found :(</title>\n    <style>\n      ::-moz-selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      ::selection {\n        background: #b3d4fc;\n        text-shadow: none;\n      }\n\n      html {\n        padding: 30px 10px;\n        font-size: 20px;\n        line-height: 1.4;\n        color: #737373;\n        background: #f0f0f0;\n        -webkit-text-size-adjust: 100%;\n        -ms-text-size-adjust: 100%;\n      }\n\n      html,\n      input {\n        font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n      }\n\n      body {\n        max-width: 500px;\n        _width: 500px;\n        padding: 30px 20px 50px;\n        border: 1px solid #b3b3b3;\n        border-radius: 4px;\n        margin: 0 auto;\n        box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;\n        background: #fcfcfc;\n      }\n\n      h1 {\n        margin: 0 10px;\n        font-size: 50px;\n        text-align: center;\n      }\n\n      h1 span {\n        color: #bbb;\n      }\n\n      h3 {\n        margin: 1.5em 0 0.5em;\n      }\n\n      p {\n        margin: 1em 0;\n      }\n\n      ul {\n        padding: 0 0 0 40px;\n        margin: 1em 0;\n      }\n\n      .container {\n        max-width: 380px;\n        _width: 380px;\n        margin: 0 auto;\n      }\n\n      /* google search */\n\n      #goog-fixurl ul {\n        list-style: none;\n        padding: 0;\n        margin: 0;\n      }\n\n      #goog-fixurl form {\n        margin: 0;\n      }\n\n      #goog-wm-qt,\n      #goog-wm-sb {\n        border: 1px solid #bbb;\n        font-size: 16px;\n        line-height: normal;\n        vertical-align: top;\n        color: #444;\n        border-radius: 2px;\n      }\n\n      #goog-wm-qt {\n        width: 220px;\n        height: 20px;\n        padding: 5px;\n        margin: 5px 10px 0 0;\n        box-shadow: inset 0 1px 1px #ccc;\n      }\n\n      #goog-wm-sb {\n        display: inline-block;\n        height: 32px;\n        padding: 0 10px;\n        margin: 5px 0 0;\n        white-space: nowrap;\n        cursor: pointer;\n        background-color: #f5f5f5;\n        background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);\n        -webkit-appearance: none;\n        -moz-appearance: none;\n        appearance: none;\n        *overflow: visible;\n        *display: inline;\n        *zoom: 1;\n      }\n\n      #goog-wm-sb:hover,\n      #goog-wm-sb:focus {\n        border-color: #aaa;\n        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);\n        background-color: #f8f8f8;\n      }\n\n      #goog-wm-qt:hover,\n      #goog-wm-qt:focus {\n        border-color: #105cb6;\n        outline: 0;\n        color: #222;\n      }\n\n      input::-moz-focus-inner {\n        padding: 0;\n        border: 0;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"container\">\n      <h1>Not found <span>:(</span></h1>\n      <p>Sorry, but the page you were trying to view does not exist.</p>\n      <p>It looks like this was the result of either:</p>\n      <ul>\n        <li>a mistyped address</li>\n        <li>an out-of-date link</li>\n      </ul>\n      <script>\n        var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;\n      </script>\n      <script src=\"//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js\"></script>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "index.js",
    "content": "var name = require('./dist/stormpath-sdk-angularjs');\nrequire('./dist/stormpath-sdk-angularjs.tpls');\n\nmodule.exports = name;\n"
  },
  {
    "path": "ngdoc_assets/example/index.ngdoc",
    "content": "@ngdoc overview\n@name Example\n@description\n\n\n## Example\n\nWe have a complete sample application which shows you how to create an\nAngularJS application with an Express backend.  Please see the example\nfolder in the repo:\n\n<a href=\"https://github.com/stormpath/stormpath-sdk-angularjs/tree/master/example\" target=\"_blank\">https://github.com/stormpath/stormpath-sdk-angularjs/tree/master/example</a>\n\n\n"
  },
  {
    "path": "ngdoc_assets/index.ngdoc",
    "content": "@ngdoc overview\n@name API Documentation\n@description\n\n# Stormpath Angular JS SDK Ng Docs\n\n[![Bower Version](https://img.shields.io/bower/v/stormpath-sdk-angularjs.svg?style=flat)](https://bower.io)\n\n## Welcome!\n\nThis is the API documentation for the Stormpath AngularJS SDK.  Here you\nwill find the detailed description of all the compontents that this\nmodule provides to your application.  With this SDK you can:\n\n* Authenticate users\n* Get the current user object\n* Know if the user is logged in\n* Use [`ui-router`][ui-router] to control access to your view states (authentication and authorization)\n\n\n## Quickstart & Getting Started\n\nIf you are just getting started with this library, we suggest the [README](https://github.com/stormpath/stormpath-sdk-angularjs) on Github."
  },
  {
    "path": "ngdoc_assets/nav.html",
    "content": "<ul class=\"nav pull-left\">\n  <li><a href=\"https://github.com/stormpath/stormpath-sdk-angularjs\" target=\"_blank\"><i class=\"icon-github icon-white\"></i> Github</a></li>\n</ul>"
  },
  {
    "path": "ngdoc_assets/server/index.ngdoc",
    "content": "@ngdoc overview\n@name Server Integration Guide\n@description\n\n# Server Integration Guide\n\nFront-end applications can not communicate with the Stormpath API directly,\nand thus need an integrated back-end.  This page has information about\nhow to integrate Stormpath into your back-end.\n\n## With Express.js\n\nIf you are using Express.js as your server, you can add our\n[Stormpath Express Module][] to your server.\n\n\n\n## With other environments\n\nIf you are using another type of server you will have to manually setup some\nserver endpoints to support this module.  Please visit\n[Stormpath Docs](https://docs.stormpath.com) to find the language SDK of your\nserver environment.\n\nUsing the SDK of your choice, you need to implement the endpoints in the\nfollowing table.  The expected URLs can be changed by modifying the URLs\nin the {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG STORMPATH_CONFIG}\n\n\n**Endpoints to implement:**\n\n<table>\n  <thead>\n    <th>Server Endpoint Description</th>\n    <th>Expected Endpoint</th>\n    <th>Stormpath SDK API to use</th>\n  </thead>\n<tbody>\n  <tr>\n    <td>\n      <p>**Current User Endpoint**</p>\n      <p>Returns a JSON object of the currently logged-in Stormpath account</p>\n    </td>\n    <td>\n      `/me`\n      <br/>\n    </td>\n    <td>\n      *N/A*\n    </td>\n  </tr>\n  <tr>\n    <td>\n      <p>**Email Verification**</p>\n      <p>Used to verify and consume email verification tokens</p>\n    </td>\n    <td>\n      `/verify`\n    </td>\n    <td>\n      [Account Verification](http://docs.stormpath.com/rest/product-guide/#verify-an-email-address)\n    </td>\n  </tr>\n  <tr>\n    <td>\n      <p>**Forgot Password**</p>\n      <p>Used to create password reset tokens, triggering a password reset email</p>\n    </td>\n    <td>\n      `/forgot`\n    </td>\n    <td>\n      [Password Reset](http://docs.stormpath.com/rest/product-guide/#reset-an-accounts-password)\n    </td>\n  </tr>\n  <tr>\n    <td>\n      <p>**Login**</p>\n      <p>\n        Used to authenticate a user and generate an access token which is stored in a secure cookie.\n        Also used to get a view model of how to render the login form. Read more about the view model [here](https://docs.stormpath.com/nodejs/express/latest/login.html#json-login-api).\n      </p>\n    </td>\n    <td>\n      `/login`\n    </td>\n    <td>\n      [Login Attempts](http://docs.stormpath.com/rest/product-guide/#authenticate-an-account)\n    </td>\n  </tr>\n  <tr>\n    <td>\n      <p>**Logout**</p>\n      <p>Used to remove any session-related cookies, such as the access token.</p>\n    </td>\n    <td>\n      `/logout`\n    </td>\n    <td>\n      *N/A*\n    </td>\n  </tr>\n  <tr>\n    <td>\n      <p>**Password Reset**</p>\n      <p>Used to complete the password reset workflow, with an sp token that\n      was issued by the forgot password flow</p>\n    </td>\n    <td>\n      `/change`\n    </td>\n    <td>\n      [Password Reset](http://docs.stormpath.com/rest/product-guide/#reset-an-accounts-password)\n    </td>\n  </tr>\n  <tr>\n    <td>\n      <p>**User Registration**</p>\n      <p>\n        Used to create new Stormpath accounts.\n        Also used to get a view model of how to render the registration form. Read more about the view model [here](https://docs.stormpath.com/nodejs/express/latest/registration.html#json-registration-api).\n      </p>\n    </td>\n    <td>\n      `/register`\n    </td>\n    <td>\n      [Account Creation](http://docs.stormpath.com/rest/product-guide/#create-an-account)\n    </td>\n  </tr>\n</tbody>\n</table>\n\n## How Sessions Work\n\nThe Angular SDK is agnostic to the authentication strategy used, it assumes that\nyou are using a cookie-based system for authenticating the browser as a client.\nHowever we do suggest that you use JWT access tokens.  You can read more in our\nblog post, [Token Based Authentication for Single Page\nApps](https://stormpath.com/blog/token-auth-spa). Our [Stormpath Express Module]\ndoes this for you.\n\nMost of our SDKs have methods for issuing JWTs, and can be used to implement\nthis strategy in your server.\n\nIf you do not want to use JWT Access Tokens, you need to ensure the following on\nyour server:\n* The {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_authentication_endpoint AUTHENTICATION_ENDPOINT} should set a cookie that identifies a session for the\nuser\n* Your protected API endpoints should respond with `401 Unauthorized` if the\nuser does not have a valid session\n\n## How Our Token Authentication Works\n\n### Token Creation and Storage\n\nWhen a user logs in, the server will issue an access token in the form of a\nJWT.  This access token will be stored in an HTTP-only cookie and will also\nset the Secure flag (so that it is only sent over HTTPS) in your production\nenvironment.\n\nA secondary refresh token will also be stored in a secure cookie, and this token\nis used to get more access tokens as they expire.  The refresh tokens can\nbe revoked, using the Stormpath REST API.\n\nYou may have heard that cookies are insecure, but that is a vague statement.\nThe truth is that HTTP-only cookies, especially Secure-only cookies, are the\nmost secure place to store authentication information because the JavaScript\nenvironment cannot access them.  This is the best way to protect yourself\nfrom XSS attacks.\n\n### Token Expiration and Revocation\n\nAccess tokens are valid until they expire.  You should set an expiration (TTL) that\nmakes sense for your application.  If you are using Stormpath to manage your access\ntokens, you can modify the TTL by modifying the OAuth Policy of the Stormpath Application\nthat you are using for your Angular Application.\n\nFor more information, please see [Using Stormpath for OAuth 2.0 and Access/Refresh Token Management][]\n\n[docs.stormpath.com]: https://docs.stormpath.com\n[ui-router]: https://github.com/angular-ui/ui-router\n[stormpath-sdk-node]: https://github.com/stormpath/stormpath-sdk-node \"Stormpath Node SDK\"\n[Stormpath Express Module]: https://github.com/stormpath/express-stormpath\n\n[Using Stormpath for OAuth 2.0 and Access/Refresh Token Management]: http://docs.stormpath.com/guides/token-management/\n"
  },
  {
    "path": "ngdoc_assets/stormpath-angular.css",
    "content": ""
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"stormpath-sdk-angularjs\",\n  \"version\": \"2.0.1\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"Stormpath, Inc.\",\n  \"license\": \"Apache-2.0\",\n  \"homepage\": \"https://github.com/stormpath/stormpath-sdk-angularjs\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/stormpath/stormpath-sdk-angularjs.git\"\n  },\n  \"devDependencies\": {\n    \"grunt-contrib-concat\": \"^0.5.1\",\n    \"grunt\": \"^0.4.5\",\n    \"load-grunt-tasks\": \"^3.4.0\",\n    \"grunt-contrib-uglify\": \"^0.11.0\",\n    \"grunt-contrib-jshint\": \"^0.11.3\",\n    \"grunt-contrib-clean\": \"^0.7.0\",\n    \"grunt-ngdocs\": \"^0.2.6\",\n    \"grunt-contrib-watch\": \"^0.6.1\",\n    \"connect-livereload\": \"^0.5.4\",\n    \"open\": \"0.0.5\",\n    \"grunt-open\": \"^0.2.3\",\n    \"grunt-contrib-copy\": \"^0.8.2\",\n    \"grunt-html2js\": \"^0.3.5\",\n    \"grunt-contrib-connect\": \"^0.11.2\",\n    \"grunt-shell\": \"^1.1.2\",\n    \"grunt-replace\": \"^0.11.0\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "protractor.conf.js",
    "content": "'use strict';\n\nexports.config = {\n  directConnect: true,\n  specs: ['test/protractor/*.js']\n};\n"
  },
  {
    "path": "src/module.js",
    "content": "'use strict';\n\n/**\n * @ngdoc object\n *\n * @name stormpath.SpStateConfig:SpStateConfig\n *\n * @property {boolean} authenticate\n *\n * If `true`, the user must be authenticated in order to view this state.\n * If the user is not authenticated, they will\n * be redirected to the `login` state.  After they login, they will be redirected to\n * the state that was originally requested.\n *\n * @property {object} authorize\n *\n * An object that defines access control rules.  Currently, it supports a group-based\n * check.  See the example below.\n *\n * @property {boolean} waitForUser\n *\n * If `true`, delay the state transition until we know\n * if the user is authenticated or not.  This is useful for situations where\n * you want everyone to see this state, but the state may look different\n * depending on the user's authentication state.\n *\n *\n * @description\n *\n * The Stormpath State Config is an object that you can define on a UI Router\n * state.  Use this configuration to define access control for your routes, as\n * defined by UI Router.\n *\n * You will need to be using the UI Router module, and you need\n * to enable the integration by calling\n * {@link stormpath.$stormpath#methods_uiRouter $stormpath.uiRouter()} in your\n * application's config block.\n *\n * If you're using Angular's built-in `$routeProvider` instead of UI Router, please\n * use {@link stormpath.$stormpath#methods_ngRouter $stormpath.ngRouter()} instead.\n *\n * **NOTE:** Do not define this configuration on a abstract state, it must go on\n * the child state.  However, the controller of the abstract state will be\n * initialized AFTER any configuration rules of the child state have been met.\n *\n * # Support for `data.authorities`\n *\n * If you have used [JHipster](https://jhipster.github.io/) to generate your\n * project, you are likely using the `data.authorities` property to define\n * authorization for your views. This library will look for the `data.authorities`\n * property and apply the same logic as our own `sp.authorize` property.\n *\n * @example\n *\n * <pre>\n *\n * angular.module('myApp')\n *   .config(function ($stateProvider) {\n *\n *     // Wait until we know if the user is logged in before showing the homepage\n *     $stateProvider\n *       .state('main', {\n *         url: '/',\n *         sp: {\n *           waitForUser: true\n *         }\n *       });\n *\n *     // Require a user to be authenticated in order to see this state\n *     $stateProvider\n *       .state('secrets', {\n *         url: '/secrets',\n *         controller: 'SecretsCtrl',\n *         sp: {\n *           authenticate: true\n *         }\n *       });\n *\n *     // Require a user to be in the admins group in order to see this state\n *     $stateProvider\n *       .state('secrets', {\n *         url: '/admin',\n *         controller: 'AdminCtrl',\n *         sp: {\n *           authorize: {\n *             group: 'admins'\n *           }\n *         }\n *       });\n * });\n * </pre>\n *\n * If using JHipster generated code:\n *\n *  <pre>\n *     // Require a user to be in the admins group in order to see this state\n *     $stateProvider\n *       .state('secrets', {\n *         url: '/admin',\n *         controller: 'AdminCtrl',\n *         data: {\n *           authorities: ['admins']\n *         }\n *       });\n *  </pre>\n */\n\n /**\n * @ngdoc object\n *\n * @name stormpath.SpRouteConfig:SpRouteConfig\n *\n * @property {boolean} authenticate\n *\n * If `true`, the user must be authenticated in order to view this route.\n * If the user is not authenticated, they will\n * be redirected to the `login` route.  After they login, they will be redirected to\n * the route that was originally requested.\n *\n * @property {object} authorize\n *\n * An object that defines access control rules.  Currently, it supports a group-based\n * check.  See the example below.\n *\n * @property {boolean} waitForUser\n *\n * If `true`, delay the route transition until we know\n * if the user is authenticated or not.  This is useful for situations where\n * you want everyone to see this route, but the route may look different\n * depending on the user's authentication route.\n *\n *\n * @description\n *\n * The Stormpath Route Config is an object that you can define on a route.\n * Use this configuration to define access control for your routes, as\n * defined by the ngRoute module.\n *\n * You will need to be using the ngRoute module, and you need\n * to enable the integration by calling\n * {@link stormpath.$stormpath#methods_ngRouter $stormpath.ngRouter()} in your\n * application's config block.\n *\n * If you're using UI Router instead of Angular's built-in `$routeProvider`, please\n * use {@link stormpath.$stormpath#methods_uiRouter $stormpath.uiRouter()} instead.\n *\n * @example\n *\n * <pre>\n *\n * angular.module('myApp')\n *   .config(function ($routeProvider) {\n *     // Wait until we know if the user is logged in before showing the homepage\n *     $routeProvider\n *       .when('/main', {\n*         controller: 'MainCtrl',\n *         sp: {\n *           waitForUser: true\n *         }\n *       });\n *\n *     // Require a user to be authenticated in order to see this route\n *     $routeProvider\n *       .when('/secrets', {\n *         controller: 'SecretsCtrl',\n *         sp: {\n *           authenticate: true\n *         }\n *       });\n *\n *     // Require a user to be in the admins group in order to see this route\n *     $routeProvider\n *       .when('/secrets', {\n *         controller: 'AdminCtrl',\n *         sp: {\n *           authorize: {\n *             group: 'admins'\n *           }\n *         }\n *       });\n * });\n * </pre>\n */\nangular.module('stormpath', [\n  'stormpath.CONFIG',\n  'stormpath.utils',\n  'stormpath.auth',\n  'stormpath.userService',\n  'stormpath.viewModelService',\n  'stormpath.socialLogin',\n  'stormpath.oauth'\n])\n\n.factory('StormpathAgentInterceptor',['$isCurrentDomain', '$spHeaders', function($isCurrentDomain, $spHeaders){\n  function StormpathAgentInterceptor(){\n\n  }\n  /**\n   * Adds the X-Stormpath-Agent header, if the requested URL is on the same\n   * domain as the current document.\n   *\n   * @param  {Object} config $http config object.\n   * @return {Object} config $http config object.\n   */\n  StormpathAgentInterceptor.prototype.request = function(config){\n\n    var uriExpressions = [\n      '/change$',\n      '/forgot$',\n      '/login$',\n      '/logout$',\n      '/me$',\n      '/oauth/token$',\n      '/oauth/token$',\n      '/register$',\n      '/revoke$',\n      '/verify$'\n    ];\n\n    if (uriExpressions.some(function(expr){\n      return new RegExp(expr).test(config.url);\n    })) {\n      config.headers = angular.extend(config.headers, $spHeaders);\n    }\n\n    return config;\n  };\n\n  return new StormpathAgentInterceptor();\n}])\n.config(['$httpProvider',function($httpProvider){\n  $httpProvider.interceptors.push('StormpathAgentInterceptor');\n}])\n.provider('$stormpath', [function $stormpathProvider(){\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.$stormpath\n   *\n   * @description\n   *\n   * This service allows you to enable application-wide features of the library.\n   *\n   * At the moment the only feature is the UI Router integration, which is\n   * documented below.\n   */\n\n  this.$get = [\n    '$user', '$injector', 'STORMPATH_CONFIG', '$rootScope', '$location',\n    function stormpathServiceFactory($user, $injector, STORMPATH_CONFIG, $rootScope, $location) {\n      var $state;\n      var $route;\n\n      function StormpathService(){\n        var encoder = new UrlEncodedFormParser();\n        this.encodeUrlForm = encoder.encode.bind(encoder);\n\n        if ($injector.has('$state')) {\n          $state = $injector.get('$state');\n        }\n\n        if ($injector.has('$route')) {\n          $route = $injector.get('$route');\n        }\n\n        return this;\n      }\n      function stateChangeUnauthenticatedEvent(toState, toParams){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$stateChangeUnauthenticated\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toState The state that the user attempted to access.\n         *\n         * @param {Object} toParams The state params of the state that the user\n         * attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a UI state change is prevented,\n         * because the user is not logged in.\n         *\n         * Use this event if you want to implement your own strategy for\n         * presenting the user with a login form.\n         *\n         * To receive this event, you must be using the UI Router integration.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$stateChangeUnauthenticated',function(e,toState,toParams){\n         *     // Your custom logic for deciding how the user should login, and\n         *     // if you want to redirect them to the desired state afterwards\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHENTICATED,toState,toParams);\n      }\n      function stateChangeUnauthorizedEvent(toState,toParams){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$stateChangeUnauthorized\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toState The state that the user attempted to access.\n         *\n         * @param {Object} toParams The state params of the state that the user\n         * attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a UI state change is prevented,\n         * because the user is not authorized by the rules defined in the\n         * {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configuration}\n         * for the requested state.\n         *\n         * Use this event if you want to implement your own strategy for telling\n         * the user that they are forbidden from viewing that state.\n         *\n         * To receive this event, you must be using the UI Router integration.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$stateChangeUnauthorized',function(e,toState,toParams){\n         *     // Your custom logic for deciding how the user should be\n         *     // notified that they are forbidden from this state\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHORIZED,toState,toParams);\n      }\n      StormpathService.prototype.stateChangeInterceptor = function stateChangeInterceptor(config) {\n        $rootScope.$on('$stateChangeStart', function(e,toState,toParams){\n          var sp = toState.sp || {}; // Grab the sp config for this state\n          var authorities = (toState.data && toState.data.authorities) ? toState.data.authorities : undefined;\n\n          if((sp.authenticate || sp.authorize || (authorities && authorities.length)) && (!$user.currentUser)){\n            e.preventDefault();\n            $user.get().then(function(){\n              // The user is authenticated, continue to the requested state\n              if(sp.authorize || (authorities && authorities.length)){\n                if(authorizeStateConfig(sp, authorities)){\n                  $state.go(toState.name,toParams);\n                }else{\n                  stateChangeUnauthorizedEvent(toState,toParams);\n                }\n              }else{\n                $state.go(toState.name,toParams);\n              }\n            },function(){\n              // The user is not authenticated, emit the necessary event\n              stateChangeUnauthenticatedEvent(toState,toParams);\n            });\n          }else if(sp.waitForUser && ($user.currentUser===null)){\n            e.preventDefault();\n            $user.get().finally(function(){\n              $state.go(toState.name,toParams);\n            });\n          }\n          else if($user.currentUser && (sp.authorize || (authorities && authorities.length))){\n            if(!authorizeStateConfig(sp, authorities)){\n              e.preventDefault();\n              stateChangeUnauthorizedEvent(toState,toParams);\n            }\n          }else if(toState.name===config.loginState){\n            /*\n              If the user is already logged in, we will redirect\n              away from the login page and send the user to the\n              post login state.\n             */\n            if($user.currentUser!==false){\n              e.preventDefault();\n              $user.get().finally(function(){\n                if($user.currentUser && $user.currentUser.href){\n                  $state.go(config.defaultPostLoginState);\n                } else {\n                  $state.go(toState.name,toParams);\n                }\n              });\n            }\n          }\n        });\n      };\n\n      function authorizeStateConfig(spStateConfig, authorities){\n        var sp = spStateConfig;\n        if(sp && sp.authorize && sp.authorize.group) {\n          return $user.currentUser.inGroup(sp.authorize.group);\n        }else if(authorities){\n          // add support for reading from JHipster's data: { authorities: ['ROLE_ADMIN'] }\n          // https://github.com/stormpath/stormpath-sdk-angularjs/issues/190\n          var roles = authorities.filter(function(authority){\n            return $user.currentUser.inGroup(authority);\n          });\n          return roles.length > 0;\n        }else{\n          console.error('Unknown authorize configuration for spStateConfig',spStateConfig);\n          return false;\n        }\n      }\n\n      function routeChangeUnauthenticatedEvent(toRoute) {\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$routeChangeUnauthenticated\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toRoute The route that the user attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a route change is prevented,\n         * because the user is not logged in.\n         *\n         * Use this event if you want to implement your own strategy for\n         * presenting the user with a login form.\n         *\n         * To receive this event, you must be using the ngRoute module.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$routeChangeUnauthenticated', function(event, toRoute) {\n         *     // Your custom logic for deciding how the user should login, and\n         *     // if you want to redirect them to the desired route afterwards\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHENTICATED, toRoute);\n      }\n\n      function routeChangeUnauthorizedEvent(toRoute) {\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.$stormpath#$routeChangeUnauthorized\n         *\n         * @eventOf stormpath.$stormpath\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {Object} toRoute The route that the user attempted to access.\n         *\n         * @description\n         *\n         * This event is broadcast when a route change is prevented,\n         * because the user is not authorized by the rules defined in the\n         * {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configuration}\n         * for the requested route.\n         *\n         * Use this event if you want to implement your own strategy for telling\n         * the user that they are forbidden from viewing that route.\n         *\n         * To receive this event, you must be using the ngRoute module.\n         *\n         * @example\n         *\n         * <pre>\n         *   $rootScope.$on('$routeChangeUnauthorized', function(event, toRoute) {\n         *     // Your custom logic for deciding how the user should be\n         *     // notified that they are forbidden from this route\n         *   });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHORIZED, toRoute);\n      }\n\n      StormpathService.prototype.routeChangeInterceptor = function routeChangeInterceptor(config) {\n        function goToRoute(route) {\n          setTimeout(function() {\n            if (route.$$route.originalPath === $location.path()) {\n              $route.reload();\n            } else {\n              $location.path(route);\n            }\n          });\n        }\n\n        $rootScope.$on('$routeChangeStart', function(event, toRoute) {\n          if (!toRoute.$$route) {\n            return;\n          }\n\n          var sp = toRoute.$$route.sp || {}; // Grab the sp config for this route\n\n          if ((sp.authenticate || sp.authorize) && !$user.currentUser) {\n            event.preventDefault();\n\n            $user.get().then(function() {\n              // The user is authenticated, continue to the requested route\n              if (sp.authorize) {\n                if (authorizeStateConfig(sp)) {\n                  goToRoute(toRoute);\n                } else {\n                  stateChangeUnauthorizedEvent(toRoute);\n                }\n              } else {\n                goToRoute(toRoute);\n              }\n            }, function() {\n              // The user is not authenticated, emit the necessary event\n              routeChangeUnauthenticatedEvent(toRoute);\n            });\n          } else if (sp.waitForUser && $user.currentUser === null) {\n            event.preventDefault();\n\n            $user.get().finally(function() {\n              goToRoute(toRoute);\n            });\n          } else if ($user.currentUser && sp.authorize) {\n            if (!authorizeStateConfig(sp)) {\n              event.preventDefault();\n              routeChangeUnauthorizedEvent(toRoute);\n            }\n          } else if (toRoute.$$route.originalPath === config.loginRoute) {\n            /*\n              If the user is already logged in, we will redirect\n              away from the login page and send the user to the\n              post login route.\n             */\n            if ($user.currentUser && $user.currentUser.href) {\n              event.preventDefault();\n              goToRoute(config.defaultPostLoginRoute);\n            }\n          }\n        });\n      };\n\n      function authorizeRouteConfig(spRouteConfig) {\n        var sp = spRouteConfig;\n\n        if (sp && sp.authorize && sp.authorize.group) {\n          return $user.currentUser.inGroup(sp.authorize.group);\n        }\n\n        console.error('Unknown authorize configuration for spRouteConfig', sp);\n        return false;\n      }\n\n      /**\n       * @ngdoc function\n       *\n       * @name stormpath#uiRouter\n       *\n       * @methodOf stormpath.$stormpath\n       *\n       * @param {object} config\n       *\n       * * **`autoRedirect`** - Defaults to true.  After the user logs in at\n       * the state defined by `loginState`, they will be redirected back to the\n       * state that was originally requested.\n       *\n       * * **`defaultPostLoginState`**  - Where the user should be sent, after login,\n       * if they have visited the login page directly.  If you do not define a value,\n       * nothing will happen at the login state.  You can alternatively use the\n       * {@link stormpath.authService.$auth#events_$authenticated $authenticated} event to know\n       * that login is successful.\n       *\n       * * **`forbiddenState`** - The UI state name that we should send the user\n       * to if they try to an access a view that they are not authorized to view.\n       * This happens in response to an `authorize` rule in one of your\n       * {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configurations}\n       *\n       * * **`loginState`** - The UI state name that we should send the user\n       * to if they need to login.  You'll probably use `login` for this value.\n       *\n       * @description\n       *\n       * Call this method to enable the integration with the UI Router module.\n       *\n       * When enabled, you can define {@link stormpath.SpStateConfig:SpStateConfig Stormpath State Configurations} on your UI states.\n       * This object allows you to define access control for the state.\n       *\n       * You can pass config options to this integration, the options control the\n       * default behavior around \"need to login\" and \"forbidden\" situations.\n       * If you wish to implement your own logic for these situations, simply\n       * omit the options and use the events (documented below) to know\n       * what is happening in the application.\n       *\n       * @example\n       *\n       * <pre>\n       * angular.module('myApp')\n       *   .run(function($stormpath){\n       *     $stormpath.uiRouter({\n       *       forbiddenState: 'forbidden',\n       *       defaultPostLoginState: 'main',\n       *       loginState: 'login'\n       *     });\n       *   });\n       * </pre>\n       */\n      StormpathService.prototype.uiRouter = function uiRouter(config){\n        var self = this;\n        config = typeof config === 'object' ? config : {};\n        this.stateChangeInterceptor(config);\n\n        if(config.loginState){\n          self.unauthenticatedWather = $rootScope.$on(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHENTICATED,function(e,toState,toParams){\n            self.postLogin = {\n              toState: toState,\n              toParams: toParams\n            };\n            $state.go(config.loginState);\n          });\n        }\n\n        $rootScope.$on(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME,function(){\n          if(self.postLogin && (config.autoRedirect !== false)){\n            $state.go(self.postLogin.toState,self.postLogin.toParams).then(function(){\n              self.postLogin = null;\n            });\n          }else if(config.defaultPostLoginState){\n            $state.go(config.defaultPostLoginState);\n          }\n        });\n\n        if(config.forbiddenState){\n          self.forbiddenWatcher = $rootScope.$on(STORMPATH_CONFIG.STATE_CHANGE_UNAUTHORIZED,function(){\n            $state.go(config.forbiddenState);\n          });\n        }\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name stormpath#ngRouter\n       *\n       * @methodOf stormpath.$stormpath\n       *\n       * @param {object} config\n       *\n       * * **`autoRedirect`** - Defaults to true.  After the user logs in at\n       * the route defined by `loginRoute`, they will be redirected back to the\n       * route that was originally requested.\n       *\n       * * **`defaultPostLoginRoute`**  - Where the user should be sent, after login,\n       * if they have visited the login page directly.  If you do not define a value,\n       * nothing will happen at the login route.  You can alternatively use the\n       * {@link stormpath.authService.$auth#events_$authenticated $authenticated} event to know\n       * that login is successful.\n       *\n       * * **`forbiddenRoute`** - The route that we should send the user\n       * to if they try to an access a view that they are not authorized to view.\n       * This happens in response to an `authorize` rule in one of your\n       * {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configurations}\n       *\n       * * **`loginRoute`** - The route name that we should send the user\n       * to if they need to login.  You'll probably use `login` for this value.\n       *\n       * @description\n       *\n       * Call this method to enable the integration with the ngRoute module.\n       *\n       * When enabled, you can define {@link stormpath.SpRouteConfig:SpRouteConfig Stormpath Route Configurations} on your routes.\n       * This object allows you to define access control for the route.\n       *\n       * You can pass config options to this integration, the options control the\n       * default behavior around \"need to login\" and \"forbidden\" situations.\n       * If you wish to implement your own logic for these situations, simply\n       * omit the options and use the events (documented below) to know\n       * what is happening in the application.\n       *\n       * @example\n       *\n       * <pre>\n       * angular.module('myApp')\n       *   .run(function($stormpath){\n       *     $stormpath.ngRouter({\n       *       forbiddenRoute: '/forbidden',\n       *       defaultPostLoginRoute: '/home',\n       *       loginRoute: '/login'\n       *     });\n       *   });\n       * </pre>\n       */\n      StormpathService.prototype.ngRouter = function ngRouter(config) {\n        var self = this;\n\n        config = typeof config === 'object' ? config : {};\n\n        this.routeChangeInterceptor(config);\n\n        if (config.loginRoute) {\n          this.unauthenticatedWather = $rootScope.$on(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHENTICATED, function(event, toRoute) {\n            self.postLogin = {\n              toRoute: toRoute\n            };\n\n            $location.path(config.loginRoute);\n          });\n        }\n\n        $rootScope.$on(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME, function() {\n          if (self.postLogin && config.autoRedirect !== false) {\n            $location.path(self.postLogin.toRoute);\n            self.postLogin = null;\n          } else if (config.defaultPostLoginRoute) {\n            $location.path(config.defaultPostLoginRoute);\n          }\n        });\n\n        if (config.forbiddenRoute) {\n          this.forbiddenWatcher = $rootScope.$on(STORMPATH_CONFIG.ROUTE_CHANGE_UNAUTHORIZED, function() {\n            $location.path(config.forbiddenRoute);\n          });\n        }\n      };\n\n      StormpathService.prototype.regexAttrParser = function regexAttrParser(value){\n        var expr;\n        if(value instanceof RegExp){\n          expr = value;\n        }else if(value && /^\\/.+\\/[gim]?$/.test(value)){\n          expr = new RegExp(value.split('/')[1],value.split('/')[2]);\n        }else{\n          expr = value;\n        }\n        return expr;\n      };\n\n      function UrlEncodedFormParser(){\n\n        // Copy & modify from https://github.com/hapijs/qs/blob/master/lib/stringify.js\n\n        this.delimiter = '&';\n        this.arrayPrefixGenerators = {\n          brackets: function (prefix) {\n            return prefix + '[]';\n          },\n          indices: function (prefix, key) {\n            return prefix + '[' + key + ']';\n          },\n          repeat: function (prefix) {\n            return prefix;\n          }\n        };\n        return this;\n      }\n      UrlEncodedFormParser.prototype.stringify = function stringify(obj, prefix, generateArrayPrefix) {\n\n        if (obj instanceof Date) {\n          obj = obj.toISOString();\n        }\n        else if (obj === null) {\n          obj = '';\n        }\n\n        if (typeof obj === 'string' ||\n          typeof obj === 'number' ||\n          typeof obj === 'boolean') {\n\n          return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];\n        }\n\n        var values = [];\n\n        if (typeof obj === 'undefined') {\n          return values;\n        }\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          if (Array.isArray(obj)) {\n            values = values.concat(this.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));\n          }\n          else {\n            values = values.concat(this.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));\n          }\n        }\n\n        return values;\n      };\n      UrlEncodedFormParser.prototype.encode = function encode(obj, options) {\n\n        options = options || {};\n        var delimiter = typeof options.delimiter === 'undefined' ? this.delimiter : options.delimiter;\n\n        var keys = [];\n\n        if (typeof obj !== 'object' ||\n          obj === null) {\n\n          return '';\n        }\n\n        var arrayFormat;\n        if (options.arrayFormat in this.arrayPrefixGenerators) {\n          arrayFormat = options.arrayFormat;\n        }\n        else if ('indices' in options) {\n          arrayFormat = options.indices ? 'indices' : 'repeat';\n        }\n        else {\n          arrayFormat = 'indices';\n        }\n\n        var generateArrayPrefix = this.arrayPrefixGenerators[arrayFormat];\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          keys = keys.concat(this.stringify(obj[key], key, generateArrayPrefix));\n        }\n\n        return keys.join(delimiter);\n      };\n\n      return new StormpathService();\n    }\n  ];\n}])\n.run(['$rootScope','$user','STORMPATH_CONFIG',function($rootScope,$user,STORMPATH_CONFIG){\n  $rootScope.user = $user.currentUser || null;\n  $user.get().finally(function(){\n    $rootScope.user = $user.currentUser;\n  });\n  $rootScope.$on(STORMPATH_CONFIG.GET_USER_EVENT,function(){\n    $rootScope.user = $user.currentUser;\n  });\n  $rootScope.$on(STORMPATH_CONFIG.SESSION_END_EVENT,function(){\n    $rootScope.user = $user.currentUser;\n  });\n  $rootScope.$on(STORMPATH_CONFIG.SESSION_END_ERROR_EVENT,function(event, error){\n    console.error('Logout error', error);\n  });\n  $rootScope.$on(STORMPATH_CONFIG.UNAUTHENTICATED_EVENT,function(event, error){\n    console.error('UNAUTHENTICATED_EVENT');\n  });\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUser:ifUser\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is logged in.\n *\n * @example\n *\n * <pre>\n * <div class=\"container\">\n *   <h3 if-user>Hello, {{user.fullName}}</h3>\n * </div>\n * </pre>\n */\n.directive('ifUser',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(user){\n        if(user && user.href){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifNotUser:ifNotUser\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is NOT logged in.\n *\n * @example\n *\n * <pre>\n * <div class=\"container\">\n *   <h3 if-not-user>Hello, you need to login</h3>\n * </div>\n * </pre>\n */\n.directive('ifNotUser',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(user){\n        if(user && user.href){\n          element.addClass('ng-hide');\n        }else{\n          element.removeClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserInGroup:ifUserInGroup\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is logged in\n * and is a member of the group that is specified by the expression.\n *\n * The attribute value MUST be one of:\n *\n * * A string expression, surrounded by quotes\n * * A reference to a property on the $scope.  That property can be a string or\n * regular expression.\n *\n * **Note**: This feature depends on the data that is returned by the\n * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_CURRENT_USER_URI CURRENT_USER_URI}.\n * Your server should expand the account's groups before returning the user.\n * If you are using [express-stormpath](https://github.com/stormpath/express-stormpath), simply use\n * [Automatic Expansion](http://docs.stormpath.com/nodejs/express/latest/user_data.html#automatic-expansion)\n *\n * # Using Regular Expressions\n *\n * If using a string expression as the attribute value, you can pass a regular\n * expression by wrapping it in the literal\n * syntax, e.g.\n *  * `'/admins/'` would match any group which has *admins* in the name\n *  * `'/admin$/'` would match any group were the name **ends with** *admin*\n *\n * If referencing a scope property, you should create the value as a RegExp type,\n * e.g.:\n *\n *  <pre>\n *    $scope.matchGroup = new RegExp(/admins/);\n *  </pre>\n *\n * All regular expressions are evaluated via\n * [RegExp.prototype.test](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test)\n *\n * @example\n *\n * <pre>\n *   <script type=\"text/javascript\">\n *     function SomeController($scope){\n *       $scope.matchGroup = /admins/;\n *     }\n *   <script>\n *   <div ng-controller=\"SomeController\">\n *     <h3 if-user-in-group=\"'admins'\">\n *       Hello, {{user.fullName}}, you are an administrator\n *     </h3>\n *\n *     <div if-user-in-group=\"'/admins/'\">\n *        <!-- would match any group which has *admins* in the name -->\n *     </div>\n *     <div if-user-in-group=\"matchGroup\">\n *        <!-- equivalent to the last example -->\n *     </div>\n *     <div if-user-in-group=\"'/admin$/'\">\n *        <!-- would match any group were the name **ends with** *admin* -->\n *     </div>\n *   </div>\n * </pre>\n */\n.directive('ifUserInGroup',['$user','$rootScope','$parse','$stormpath',function($user,$rootScope,$parse,$stormpath){\n\n  return {\n    link: function(scope,element,attrs){\n\n      var expr;\n      var attrExpr = attrs.ifUserInGroup;\n\n      function evalElement(){\n        var user = $user.currentUser;\n        if(user && user.groupTest(expr || attrExpr)){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      }\n\n      if(attrExpr){\n        scope.$watch($parse(attrExpr),function(value){\n          expr = $stormpath.regexAttrParser(value);\n          evalElement();\n        });\n        $rootScope.$watch('user',function(){\n          evalElement();\n        });\n      }\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserNotInGroup:ifUserNotInGroup\n *\n * @description\n *\n * Use this directive to conditionally show an element if the user is logged in\n * and is NOT a member of the group that is specified by the expression.\n *\n * This is the inverse of {@link stormpath.ifUserInGroup:ifUserInGroup ifUserInGroup},\n * please refer to that directive for full usage information.\n *\n * **Note**: This feature depends on the data that is returned by the\n * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_CURRENT_USER_URI CURRENT_USER_URI}.\n * Your server should expand the account's groups before returning the user.\n * If you are using [express-stormpath](https://github.com/stormpath/express-stormpath), simply use\n * [Automatic Expansion](http://docs.stormpath.com/nodejs/express/latest/user_data.html#automatic-expansion)\n *\n * @example\n *\n * <pre>\n *   <div class=\"container\">\n *     <h3 if-user-not-in-group=\"'admins'\">\n *       Hello, {{user.fullName}}, please request administrator access\n *     </h3>\n *   </div>\n * </pre>\n */\n.directive('ifUserNotInGroup',['$user','$rootScope','$parse','$stormpath',function($user,$rootScope,$parse,$stormpath){\n  return {\n    link: function(scope,element,attrs){\n\n      var expr;\n      var attrExpr = attrs.ifUserNotInGroup;\n\n      function evalElement(){\n        var user = $user.currentUser;\n        if(user && user.groupTest(expr || attrExpr)){\n          element.addClass('ng-hide');\n        }else{\n          element.removeClass('ng-hide');\n        }\n      }\n\n      if(attrExpr){\n        scope.$watch($parse(attrExpr),function(value){\n          expr = $stormpath.regexAttrParser(value);\n          evalElement();\n        });\n        $rootScope.$watch('user',function(){\n          evalElement();\n        });\n      }\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.whileResolvingUser:while-resolving-user\n *\n * @description\n *\n * # [DEPRECATED]\n * Please use {@link stormpath.ifUserStateUnknown:ifUserStateUnknown ifUserStateUnknown} instead.\n *\n */\n.directive('whileResolvingUser',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(){\n        if($user.currentUser || ($user.currentUser===false)){\n          element.addClass('ng-hide');\n        }else{\n          element.removeClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserStateKnown:ifUserStateKnown\n *\n * @description\n *\n * Use this directive to show an element once the user state is known.\n * The inverse of {@link stormpath.ifUserStateUnknown:ifUserStateUnknown ifUserStateUnknown}. You can\n * use this directive to show an element after we know if the user is logged in\n * or not.\n *\n * @example\n *\n * <pre>\n * <div if-user-state-known>\n *   <li if-not-user>\n *      <a ui-sref=\"login\">Login</a>\n *    </li>\n *    <li if-user>\n *        <a ui-sref=\"main\" sp-logout>Logout</a>\n *    </li>\n * </div>\n * </pre>\n */\n.directive('ifUserStateKnown',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(){\n        if($user.currentUser || ($user.currentUser===false)){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n/**\n * @ngdoc directive\n *\n * @name stormpath.ifUserStateUnknown:ifUserStateUnknown\n *\n * @description\n *\n * Use this directive to show an element while waiting to know if the user\n * is logged in or not.  This is useful if you want to show a loading graphic\n * over your application while you are waiting for the user state.\n *\n * @example\n *\n * <pre>\n * <div if-user-state-unknown>\n *   <p>Loading.. </p>\n * </div>\n * </pre>\n */\n.directive('ifUserStateUnknown',['$user','$rootScope',function($user,$rootScope){\n  return {\n    link: function(scope,element){\n      $rootScope.$watch('user',function(){\n        if($user.currentUser === null){\n          element.removeClass('ng-hide');\n        }else{\n          element.addClass('ng-hide');\n        }\n      });\n    }\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spLogout:spLogout\n *\n * @description\n *\n * This directive adds a click handler to the element.  When clicked, the user will be logged out.\n *\n * **Note**: the click action triggers the logout request to the server and\n * deletes your authentication information, it does not automatically redirect\n * you to any view (we leave this in your control).\n *\n * The common use-case is to redirect users to the login view after they\n * logout.  This can be done by observing the\n * {@link stormpath.authService.$auth#events_$sessionEnd $sessionEnd} event.\n * For example, if you are using UI Router:\n *\n * ```javascript\n * $rootScope.$on('$sessionEnd',function () {\n *   $state.transitionTo('login');\n * });\n * ```\n *\n * @example\n *\n * <pre>\n *   <a ui-sref=\"main\" sp-logout>Logout</a>\n * </pre>\n */\n.directive('spLogout',['$auth',function($auth){\n  return{\n    link: function(scope,element){\n      element.on('click',function(){\n        $auth.endSession();\n      });\n    }\n  };\n}]);\n"
  },
  {
    "path": "src/spEmailVerification.tpl.html",
    "content": "<div class=\"row\">\n  <div class=\"col-sm-offset-4 col-xs-12 col-sm-4\">\n    <p ng-show=\"verifying\" class=\"alert alert-warning\">We are verifying your account</p>\n    <p ng-show=\"verified\" class=\"alert alert-success\">\n      Your account has has been verified!\n      <a href=\"/login\">Login Now.</a>\n    </p>\n    <p ng-show=\"reVerificationSent\" class=\"alert alert-success\">\n      We have sent a new verification message to your email address, please check your email for this message.\n    </p>\n    <div ng-show=\"showVerificationError\" class=\"alert alert-danger\">\n      This email verification link is not valid.  If you need us\n      to re-send an email verification message, please enter your email address or username\n      below.\n    </div>\n    <div ng-show=\"resendFailed\" class=\"alert alert-danger\">\n      Sorry, there was a problem with that email or username.  Please try again.\n    </div>\n  </div>\n</div>\n<div class=\"row\">\n  <div class=\"col-xs-12\">\n    <form class=\"form-horizontal\" ng-show=\"needsReVerification && !reVerificationSent\" ng-submit=\"submit()\">\n\n      <div class=\"form-group\">\n        <label for=\"spEmail\" class=\"col-xs-12 col-sm-4 control-label\">Email or Username</label>\n        <div class=\"col-xs-12 col-sm-4\">\n          <input class=\"form-control\" id=\"spUsername\" ng-model=\"formModel.username\" placeholder=\"Username or Email\" ng-disabled=\"posting\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-sm-offset-4 col-xs-12\">\n          <p class=\"text-danger\" ng-show=\"error\" ng-bind=\"error\"></p>\n          <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"posting\">Re-Send Verification</button>\n        </div>\n      </div>\n    </form>\n  </div>\n</div>\n"
  },
  {
    "path": "src/spLoginForm.tpl.html",
    "content": "<style>\n  .btn.btn-social {\n    margin-right: 7px;\n    min-width: 100px;\n  }\n\n  .btn.btn-facebook {\n    color: white;\n    background-color: #3B5998;\n    border-color: #37528C;\n  }\n  .btn.btn-facebook:hover,\n  .btn.btn-facebook:focus {\n    color: white;\n    background-color: #2F487B;\n    border-color: #2F487B;\n  }\n\n  .btn.btn-google {\n    color: white;\n    background-color: #dc4e41;\n    border-color: #C1453A;\n  }\n  .btn.btn-google:hover,\n  .btn.btn-google:focus {\n    color: white;\n    background-color: #C74539;\n    border-color: #AF4138;\n  }\n\n  .sp-loading {\n    text-align: center;\n  }\n</style>\n\n<div class=\"row\">\n  <div class=\"col-xs-12\">\n    <div ng-show=\"!viewModel\" class=\"sp-loading\">\n      Loading...\n    </div>\n    <form class=\"form-horizontal\" ng-hide=\"accepted || !viewModel\" ng-submit=\"submit()\">\n      <div class=\"form-group\" ng-repeat=\"field in viewModel.form.fields\">\n        <label for=\"sp-{{field.name}}\" class=\"col-xs-12 col-sm-4 control-label\">{{field.label}}</label>\n        <div class=\"col-xs-12 col-sm-4\">\n          <input class=\"form-control\" name=\"{{field.name}}\" id=\"sp-{{field.name}}\" type=\"{{field.type}}\" ng-model=\"formModel[field.name]\" placeholder=\"{{field.placeholder}}\" ng-disabled=\"posting\" ng-required=\"field.required\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-sm-offset-4 col-sm-4\">\n          <p class=\"text-danger\" ng-show=\"error\" ng-bind=\"error\"></p>\n          <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"posting\">Login</button>\n          <a href=\"/forgot\" class=\"pull-right\">Forgot Password</a>\n        </div>\n      </div>\n      <div class=\"form-group\" ng-show=\"viewModel.accountStores.length\">\n        <div class=\"col-sm-offset-4 col-sm-4\">\n          <p>Or login with:</p>\n          <button ng-repeat=\"accountStore in viewModel.accountStores\" type=\"button\" class=\"btn btn-social btn-{{accountStore.provider.providerId}}\" sp-social-login=\"accountStore\" sp-options=\"{{accountStore.provider}}\" style=\"text-transform: capitalize;\">\n            {{providerName}}\n          </button>\n        </div>\n      </div>\n    </form>\n  </div>\n</div>\n"
  },
  {
    "path": "src/spPasswordResetForm.tpl.html",
    "content": "<div class=\"row\">\n  <div class=\"col-sm-offset-4 col-xs-12 col-sm-4\">\n    <p ng-show=\"verifying\" class=\"alert alert-warning text-center\">We are verifying this link</p>\n    <p class=\"alert alert-success\" ng-show=\"reset\">Your new password has been set.  Please <a href=\"/login\">Login Now</a>.</p>\n    <div ng-show=\"showVerificationError\" class=\"alert alert-danger\">\n      This password reset link is not valid.  You may request another\n      link by <a href=\"/forgot\">clicking here</a>.\n    </div>\n  </div>\n</div>\n<div class=\"row\">\n  <div class=\"col-xs-12\">\n    <form class=\"form-horizontal\" ng-show=\"verified && !reset\" ng-submit=\"submit()\">\n\n      <div class=\"form-group\">\n        <label for=\"spEmail\" class=\"col-xs-12 col-sm-4 control-label\">New Password</label>\n        <div class=\"col-xs-12 col-sm-4\">\n          <input class=\"form-control\" id=\"spUsername\" ng-model=\"formModel.password\" placeholder=\"New Password\" type=\"password\" ng-disabled=\"posting\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <label for=\"spEmail\" class=\"col-xs-12 col-sm-4 control-label\">Confirm New Password</label>\n        <div class=\"col-xs-12 col-sm-4\">\n          <input class=\"form-control\" id=\"spUsername\" ng-model=\"formModel.confirmPassword\" placeholder=\"Confirm New Password\" type=\"password\" ng-disabled=\"posting\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-sm-offset-4 col-sm-4\">\n          <p class=\"alert alert-danger\" ng-show=\"error\" ng-bind=\"error\"></p>\n          <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"posting\">Set New Password</button>\n        </div>\n      </div>\n    </form>\n  </div>\n</div>\n"
  },
  {
    "path": "src/spPasswordResetRequestForm.tpl.html",
    "content": "<div class=\"row\">\n  <div class=\"col-sm-offset-4 col-xs-12 col-sm-4\">\n    <p ng-show=\"sent\" class=\"alert alert-success\">\n      We have sent a password reset link to the email address of the account that you specified.\n      Please check your email for this message, then click on the link.\n    </p>\n    <p ng-show=\"sent\" class=\"pull-right\">\n      <a href=\"/login\">Back to Login</a>\n    </p>\n    <div ng-show=\"error\" class=\"alert alert-danger\" ng-bind=\"error\"></div>\n  </div>\n</div>\n<div class=\"row\">\n  <div class=\"col-xs-12\">\n    <form class=\"form-horizontal\" ng-hide=\"sent\" ng-submit=\"submit()\">\n\n      <div class=\"form-group\">\n        <label for=\"spEmail\" class=\"col-xs-12 col-sm-4 control-label\">Email or Username</label>\n        <div class=\"col-xs-12 col-sm-4\">\n          <input class=\"form-control\" id=\"spEmail\" ng-model=\"formModel.email\" placeholder=\"Your Email Address\" ng-disabled=\"posting\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-sm-offset-4 col-xs-12\">\n          <p class=\"text-danger\" ng-show=\"error\" ng-bind=\"error\"></p>\n          <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"posting\">Request Password Reset</button>\n        </div>\n      </div>\n    </form>\n  </div>\n</div>\n"
  },
  {
    "path": "src/spRegistrationForm.tpl.html",
    "content": "<style>\n  .btn.btn-social {\n    margin-right: 7px;\n    min-width: 100px;\n  }\n\n  .btn.btn-facebook {\n    color: white;\n    background-color: #3B5998;\n    border-color: #37528C;\n  }\n  .btn.btn-facebook:hover,\n  .btn.btn-facebook:focus {\n    color: white;\n    background-color: #2F487B;\n    border-color: #2F487B;\n  }\n\n  .btn.btn-google {\n    color: white;\n    background-color: #dc4e41;\n    border-color: #C1453A;\n  }\n  .btn.btn-google:hover,\n  .btn.btn-google:focus {\n    color: white;\n    background-color: #C74539;\n    border-color: #AF4138;\n  }\n\n  .sp-loading {\n    text-align: center;\n  }\n</style>\n\n<div class=\"row\">\n  <div class=\"col-sm-offset-4 col-xs-12 col-sm-4\">\n    <p class=\"alert alert-success\" ng-show=\"created && !enabled\">Your account has been created.  Please check your email for a verification link.</p>\n    <p ng-show=\"created && !enabled\" class=\"pull-right\">\n      <a href=\"/login\">Back to Login</a>\n    </p>\n    <p class=\"alert alert-success\" ng-show=\"created && enabled && !authenticating\">Your account has been created.  <a href=\"/login\">Login Now</a>.</p>\n  </div>\n</div>\n<div class=\"row\">\n  <div class=\"col-xs-12\">\n    <div ng-show=\"!viewModel\" class=\"sp-loading\">\n      Loading...\n    </div>\n    <form class=\"form-horizontal\" ng-hide=\"!viewModel || (created && !authenticating)\" ng-submit=\"submit()\">\n      <div class=\"form-group\" ng-repeat=\"field in viewModel.form.fields\">\n        <label for=\"sp-{{field.name}}\" class=\"col-xs-12 col-sm-4 control-label\">{{field.label}}</label>\n        <div class=\"col-xs-12 col-sm-4\">\n          <input class=\"form-control\" name=\"{{field.name}}\" id=\"sp-{{field.name}}\" type=\"{{field.type}}\" ng-model=\"formModel[field.name]\" placeholder=\"{{field.placeholder}}\" ng-disabled=\"creating\" ng-required=\"field.required\">\n        </div>\n      </div>\n      <div class=\"form-group\">\n        <div class=\"col-sm-offset-4 col-sm-4\">\n          <p class=\"alert alert-danger\" ng-show=\"error\" ng-bind=\"error\"></p>\n          <button type=\"submit\" class=\"btn btn-primary\" ng-disabled=\"creating\">Register</button>\n        </div>\n      </div>\n      <div class=\"form-group\" ng-show=\"viewModel.accountStores.length\">\n        <div class=\"col-sm-offset-4 col-sm-4\">\n          <p>Or register with:</p>\n          <button ng-repeat=\"accountStore in viewModel.accountStores\" type=\"button\" class=\"btn btn-social btn-{{accountStore.provider.providerId}}\" sp-social-login=\"accountStore\" sp-options=\"{{accountStore.provider}}\" style=\"text-transform: capitalize;\">\n            {{providerName}}\n          </button>\n        </div>\n      </div>\n    </form>\n  </div>\n</div>"
  },
  {
    "path": "src/stormpath.auth.js",
    "content": "'use strict';\n/**\n * @ngdoc overview\n *\n * @name  stormpath.authService\n *\n * @description\n *\n * This module provides the {@link stormpath.authService.$auth $auth} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\n/**\n * @ngdoc object\n *\n * @name stormpath.authService.$authProvider\n *\n * @description\n *\n * Provides the {@link stormpath.authService.$auth $auth} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\nangular.module('stormpath.auth',['stormpath.CONFIG', 'stormpath.oauth', 'stormpath.utils'])\n.config(['$injector','STORMPATH_CONFIG',function $authProvider($injector,STORMPATH_CONFIG){\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.authService.$auth\n   *\n   * @description\n   *\n   * The auth service provides methods for authenticating a user, aka\n   * \"logging in\" the user.\n   */\n  var authServiceProvider = {\n    $get: ['$http','$user','$rootScope','$spFormEncoder','$q','$spErrorTransformer', '$isCurrentDomain', 'StormpathOAuth', function authServiceFactory($http,$user,$rootScope,$spFormEncoder,$q, $spErrorTransformer, $isCurrentDomain, StormpathOAuth){\n\n      function AuthService(){\n        return this;\n      }\n      AuthService.prototype.authenticate = function authenticate(data) {\n        /**\n         * @ngdoc function\n         *\n         * @name  stormpath.authService.$auth#authenticate\n         *\n         * @methodOf stormpath.authService.$auth\n         *\n         * @param {Object} credentialData\n         *\n         * An object literal for passing username & password, or social provider\n         * token.\n         *\n         * @returns {promise}\n         *\n         * A promise that is resolved with the authentication response or error\n         * response (both are response objects from the $http service).\n         *\n         * @description\n         *\n         * Logs the user in.\n         *\n         * Sends the provided credential data to your backend server. The server\n         * handler should verify the credentials and return an access token,\n         * which is stored in an HTTP-only cookie.\n         *\n         * @example\n         *\n         * ## Username & Password example\n         *\n         * <pre>\n         * myApp.controller('LoginCtrl', function ($scope, $auth, $state) {\n         *   $scope.errorMessage = null;\n         *   $scope.formData = {\n         *     username: '',         // Expose to user as email/username field\n         *     password: '',\n         *   };\n         *\n         *   // Use this method with ng-submit on your form\n         *   $scope.login = function login(formData){\n         *     $auth.authenticate(formData)\n         *      .then(function(){\n         *        console.log('login success');\n         *        $state.go('home');\n         *      })\n         *      .catch(function(err){\n         *        $scope.errorMessage = err.message;\n         *      });\n         *   }\n         *\n         * });\n         * </pre>\n         *\n         * ## Social Login example\n         *\n         * <pre>\n         * myApp.controller('LoginCtrl', function ($scope, $auth, $state) {\n         *   $scope.errorMessage = null;\n         *   $scope.formData = {\n         *     providerId: 'facebook',         // Get access token from FB sdk login\n         *     accessToken: 'CABTmZxAZBxBADbr1l7ZCwHpjivBt9T0GZBqjQdTmgyO0OkUq37HYaBi4F23f49f5',\n         *   };\n         *\n         *   // Use this method with ng-submit on your form\n         *   $scope.login = function login(formData){\n         *     $auth.authenticate(formData)\n         *      .then(function(){\n         *        console.log('login success');\n         *        $state.go('home');\n         *      })\n         *      .catch(function(err){\n         *        $scope.errorMessage = err.message;\n         *      });\n         *   }\n         *\n         * });\n         * </pre>\n         */\n\n\n        function success(httpResponse){\n          $user.get(true).then(function(){\n            authenticatedEvent(httpResponse);\n          });\n        }\n\n        function error(httpResponse){\n          authenticationFailureEvent(httpResponse);\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        }\n\n        var headers = {\n          Accept: 'application/json'\n        };\n\n        var authEndpoint = STORMPATH_CONFIG.getUrl('AUTHENTICATION_ENDPOINT');\n        var op;\n\n        if ($isCurrentDomain(authEndpoint)) {\n          op = $http($spFormEncoder.formPost({\n            url: authEndpoint,\n            method: 'POST',\n            headers: headers,\n            withCredentials: true,\n            data: data\n          }));\n        } else {\n          var remoteData = angular.extend({}, data);\n\n          // Handles different naming expected in local and client API login\n          if (remoteData.login) {\n            remoteData.username = remoteData.login;\n            delete remoteData.login;\n          }\n\n          op = StormpathOAuth.authenticate(remoteData, headers);\n        }\n\n        return op.then(success, error);\n      };\n\n      /**\n       * @ngdoc event\n       *\n       * @name stormpath.authService.$user#$sessionEnd\n       *\n       * @eventOf stormpath.authService.$auth\n       *\n       * @eventType broadcast on root scope\n       *\n       * @param {Object} event\n       *\n       * Angular event object.\n\n       * @description\n       *\n       * This event is broadcast when a call to\n       * {@link stormpath.authService.$auth#methods_endSession $auth.endSession()}\n       * is successful.  Use this event when you want to do something after the\n       * user has logged out.\n       */\n      function endSessionEvent () {\n        $rootScope.$broadcast(STORMPATH_CONFIG.SESSION_END_EVENT);\n      }\n\n      /**\n       * @ngdoc function\n       *\n       * @name stormpath.authService.$auth#endSession\n       *\n       * @methodOf stormpath.authService.$auth\n       *\n       * @return {promise} A promise that is resolved when the logout request\n       * of the server is complete.\n       *\n       * @description Use this method to log the user out. It triggers a request\n       * to the `/logout` endpoint on the server.  This will delete the cookies\n       * that are used for authentication.  The\n       * {@link stormpath.authService.$auth#events_$sessionEnd $sessionEnd}\n       * event will be emitted after a successful logout.\n       */\n      AuthService.prototype.endSession = function endSession(){\n        var destroyEndpoint = STORMPATH_CONFIG.getUrl('DESTROY_SESSION_ENDPOINT');\n        var op;\n\n        if ($isCurrentDomain(destroyEndpoint)) {\n          op = $http.post(destroyEndpoint, null, {\n            headers: {\n              'Accept': 'application/json',\n              'Content-Type': 'application/x-www-form-urlencoded'\n            }\n          });\n        } else {\n          op = StormpathOAuth.revoke();\n        }\n\n        op.finally(function(){\n          endSessionEvent();\n        }).catch(function(httpResponse){\n          $rootScope.$broadcast(STORMPATH_CONFIG.SESSION_END_ERROR_EVENT, httpResponse);\n        });\n\n        return op;\n      };\n\n      function authenticatedEvent(response){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.authService.$auth#$authenticated\n         *\n         * @eventOf stormpath.authService.$auth\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {httpResponse} httpResponse\n         *\n         * The http response from the $http service.  If you are writing your access tokens to the response body\n         * when a user authenticates, you will want to use this response object to get access to that token.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.authService.$auth#methods_authenticate $auth.authenticate()}\n         * is successful.\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME,response);\n      }\n      function authenticationFailureEvent(response){\n        $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_FAILURE_EVENT_NAME,response);\n      }\n      return new AuthService();\n    }]\n  };\n\n  $injector.get('$provide')\n    .provider(STORMPATH_CONFIG.AUTH_SERVICE_NAME,authServiceProvider);\n\n}]);\n"
  },
  {
    "path": "src/stormpath.config.js",
    "content": "'use strict';\n\n/**\n* @ngdoc object\n*\n* @name stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n*\n* @description\n*\n* This constant allows you to configure the internal settings of the module,\n* such as authentication endpoints and the names of events. These properties\n* must be modified within a config block.\n*\n* **Example:**\n* <pre>\n*     angular.module('myapp')\n*       .config(function(STORMPATH_CONFIG){\n*           STORMPATH_CONFIG.ENDPOINT_PREFIX = 'http://api.mydomain.com';\n*       });\n* </pre>\n*/\n\nangular.module('stormpath.CONFIG',[])\n.constant('STORMPATH_CONFIG',(function stormpathConfigBuilder(){\n  var c={\n    /**\n    * @ngdoc property\n    *\n    * @name AUTHENTICATION_SUCCESS_EVENT_NAME\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$authenticated`\n    *\n    * The name of the event that is fired when a user logs in, after\n    * successfully submitting the login form.\n    *\n    */\n    AUTHENTICATION_SUCCESS_EVENT_NAME: '$authenticated',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name AUTHENTICATION_FAILURE_EVENT_NAME\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$authenticationFailure`\n    *\n    * The name of the event that is fired when the user posts\n    * invalid login credentials to the login form.\n    */\n    AUTHENTICATION_FAILURE_EVENT_NAME: '$authenticationFailure',\n\n\n    /**\n     * @ngdoc property\n     *\n     * @name AUTH_SERVICE_NAME\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Default: `$auth`\n     *\n     * The name of the authentication service, this changes the\n     * service name that you inject.\n    */\n    AUTH_SERVICE_NAME: '$auth',\n\n    /**\n     * @ngdoc property\n     *\n     * @name AUTO_AUTHORIZED_URIS\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Default: `['/me$']`\n     *\n     * The list of URLs to match when making requests.  If an OAuth strategy is\n     * being used and the request matches this URL, this library will automatically\n     * add the `Authorization: Bearer <token>` header to the request.\n    */\n    AUTO_AUTHORIZED_URIS: ['/me$'],\n\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_SERVICE_NAME\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Default: `$socialLogin`\n     *\n     * The name of the social login service, this changes the\n     * service name that you inject.\n    */\n    SOCIAL_LOGIN_SERVICE_NAME: '$socialLogin',\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_RESPONSE_TYPE\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * The response type requested from the Stormpath Social Login v2 API.\n     * Determines the type of token that will be returned for OAuth authentication\n     * against the Stormpath OAuth API, when making social login attempts.\n    */\n    SOCIAL_LOGIN_RESPONSE_TYPE: 'stormpath_token',\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_OPTIONS\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * Options that are set for a given social authentication provider when\n     * making a social authentication request. These are appended to the request\n     * as query parameters, and will override any default options, or options\n     * set in the Stormpath admin console.\n     *\n     * The settings are mapped by providerId of a directory (e.g. `google`, `facebook`).\n     *\n     * Additional providers may be added to the object, but must all be in lowercase.\n    */\n    SOCIAL_LOGIN_OPTIONS: {\n      google: {},\n      facebook: {},\n      twitter: {},\n      linkedin: {}\n    },\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_REDIRECT_URI\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * The URI that the social login flow will redirect to after a login attempt.\n     * This URI is relative to the base application URI.\n    */\n    SOCIAL_LOGIN_REDIRECT_URI: '',\n\n    /**\n     * @ngdoc property\n     *\n     * @name SOCIAL_LOGIN_AUTHORIZE_URI\n     *\n     * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n     *\n     * @description\n     *\n     * The relative URI of the endpoint used for social auth.\n     * Should <b>not</b> be changed if Client API is used.\n    */\n    SOCIAL_LOGIN_AUTHORIZE_ENDPOINT: '/authorize',\n\n    /**\n    * @ngdoc property\n    *\n    * @name AUTHENTICATION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/login`\n    *\n    * The URI that the login form will post to.  The endpoint MUST accept data\n    * in the following format:\n    *\n    * ```\n    * {\n    *     username: '',\n    *     password: ''\n    * }\n    * ```\n    */\n    AUTHENTICATION_ENDPOINT: '/login',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name CURRENT_USER_URI\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/me`\n    *\n    * The URI that is used to fetch the account object of\n    * the currently logged in user.  This endpoint MUST:\n    *  * Respond with a JSON object that is the Stormpath account object,\n    *  if the user has an active session.\n    *  * Respond with `401 Unauthorized` if the user has no session.\n    */\n    CURRENT_USER_URI: '/me',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name DESTROY_SESSION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/logout`\n    *\n    * The URL that the {@link stormpath.spLogout:spLogout spLogout} directive\n    * will make a GET request to, this endpoint MUST delete the access token\n    * cookie, XSRF token cookie, and any other cookies that relate to the user\n    * session.\n    */\n    DESTROY_SESSION_ENDPOINT: '/logout',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name EMAIL_VERIFICATION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/verify`\n    *\n    * The endpoint that is used for verifying an account that requires email\n    * verification.  Used by\n    * {@link stormpath.userService.$user#methods_verify $user.verify()} to POST\n    * the `sptoken` that was delivered to the user by email.\n    *\n    * This endpoint MUST accept a POST request with the following format and\n    * use Stormpath to verify the token:\n    * ```\n    * {\n    *   sptoken: '<token from email sent to user>'\n    * }\n    * ```\n    *\n    */\n    EMAIL_VERIFICATION_ENDPOINT: '/verify',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name ENDPOINT_PREFIX\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: *none*\n    *\n    * A prefix, e.g. \"base URL\" to add to all endpoints that are used by this SDK.\n    * Use this if your backend API is running on a different port or domain than\n    * your Angular application.  Omit the trailing forward slash.\n    *\n    * **NOTE:** This may trigger\n    * [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)\n    * behaviour in the browser, and your server\n    * will need to respond to requests accordingly.  If you are using our\n    * Express SDK see\n    * [allowedOrigins](https://github.com/stormpath/stormpath-sdk-express#allowedOrigins)\n    *\n    * **Example:**\n    * <pre>\n    *   ENDPOINT_PREFIX = 'http://api.mydomain.com'\n    * </pre>\n    */\n    ENDPOINT_PREFIX: '',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name GET_USER_EVENT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$currentUser`\n    *\n    * The name of the event that is fired when\n    * {@link stormpath.userService.$user#methods_get $user.get()}\n    * is resolved with a user object.\n    */\n    GET_USER_EVENT: '$currentUser',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name NOT_LOGGED_IN_EVENT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$notLoggedin`\n    *\n    * The name of the event that is fired when\n    * {@link stormpath.userService.$user#methods_get $user.get()}\n    * is rejected without a user.\n    */\n    NOT_LOGGED_IN_EVENT: '$notLoggedin',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name FORGOT_PASSWORD_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/forgot`\n    *\n    * The endpoint that is used by\n    * {@link stormpath.userService.$user#methods_passwordResetRequest $user.passwordResetRequest()}\n    * to create password reset tokens.\n    */\n    FORGOT_PASSWORD_ENDPOINT: '/forgot',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name CHANGE_PASSWORD_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/change`\n    *\n    * The endpoint that is used by\n    * {@link stormpath.userService.$user#methods_verifyPasswordResetToken $user.verifyPasswordResetToken()} and\n    * {@link stormpath.userService.$user#methods_resetPassword $user.resetPassword()}\n    * to verify and consume password reset tokens (change a user's password with the token).\n    */\n    CHANGE_PASSWORD_ENDPOINT: '/change',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name SESSION_END_EVENT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$sessionEnd`\n    *\n    * The name of the event that is fired when the user logs out via the\n    * {@link stormpath.spLogout:spLogout spLogout}\n    * directive\n    */\n    SESSION_END_EVENT: '$sessionEnd',\n\n    SESSION_END_ERROR_EVENT: '$sessionEndError',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name STATE_CHANGE_UNAUTHENTICATED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$stateChangeUnauthenticated`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * UI Router state that requires authentication, but the user is not\n    * authenticated.\n    */\n    STATE_CHANGE_UNAUTHENTICATED: '$stateChangeUnauthenticated',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name STATE_CHANGE_UNAUTHORIZED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$stateChangeUnauthorized`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * UI Router state that has an access control rule which the user does not\n    * meet (such as not being in a specified group)\n    */\n    STATE_CHANGE_UNAUTHORIZED: '$stateChangeUnauthorized',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name ROUTE_CHANGE_UNAUTHENTICATED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$routeChangeUnauthenticated`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * route that requires authentication, but the user is not\n    * authenticated.\n    */\n    ROUTE_CHANGE_UNAUTHENTICATED: '$routeChangeUnauthenticated',\n\n\n    /**\n    * @ngdoc property\n    *\n    * @name ROUTE_CHANGE_UNAUTHORIZED\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$routeChangeUnauthorized`\n    *\n    * The name of the event that is fired when the user attempts to visit a\n    * route that has an access control rule which the user does not\n    * meet (such as not being in a specified group)\n    */\n    ROUTE_CHANGE_UNAUTHORIZED: '$routeChangeUnauthorized',\n\n    /**\n    * @ngdoc property\n    *\n    * @name OAUTH_REQUEST_ERROR\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$oAuthRequestError`\n    *\n    * The name of the event that is fired when the user attempts OAuth-based\n    * authentication, and fails due to an OAuth issue.\n    */\n    OAUTH_REQUEST_ERROR: '$oAuthRequestError',\n\n    /**\n    * @ngdoc property\n    *\n    * @name OAUTH_AUTHENTICATION_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/oauth/token`\n    *\n    * The endpoint that is used to authenticate and refresh using OAuth tokens.\n    * This endpoint MUST support password and refresh_token grant authentication\n    * flows.\n    */\n    OAUTH_AUTHENTICATION_ENDPOINT: '/oauth/token',\n\n    /**\n    * @ngdoc property\n    * @name OAUTH_REVOKE_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/oauth/revoke`\n    *\n    * The endpoint that is used to revoke OAuth tokens.\n    */\n    OAUTH_REVOKE_ENDPOINT: '/oauth/revoke',\n\n    /**\n    * @ngdoc property\n    * @name OAUTH_REVOKE_ENDPOINT\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * The name under which tokens are stored in the token storage mechanism.\n    * Might not be relevant if the underlying storage mechanism is not key-value\n    * based.\n    *\n    * See {@link stormpath.tokenStore.TokenStoreManager TokenStoreManager} for more detail.\n    */\n    OAUTH_TOKEN_STORAGE_NAME: 'stormpath:token',\n\n    /**\n    * @ngdoc property\n    *\n    * @name REGISTER_URI\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `/register`\n    *\n    * The endpoint that is used by\n    * {@link stormpath.userService.$user#methods_create $user.create()}\n    * to POST new users.  This endpoint MUST accept a stormpath account object\n    * and use Stormpath to create the new user.\n    */\n    REGISTER_URI: '/register',\n\n    /**\n    * @ngdoc property\n    *\n    * @name REGISTERED_EVENT_NAME\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `$registered`\n    *\n    * The name of the event that is fired when\n    * {@link stormpath.userService.$user#methods_create $user.create()}\n    * is resolved with an account that was successfully created\n    */\n    REGISTERED_EVENT_NAME: '$registered',\n\n    /**\n    * @ngdoc property\n    *\n    * @name OAUTH_DEFAULT_TOKEN_STORE_TYPE\n    *\n    * @propertyOf stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n    *\n    * @description\n    *\n    * Default: `localStorage`\n    *\n    * The default type of local storage used by\n    * {@link stormpath.oauth.StormpathOAuthTokenProvider}.\n    */\n    OAUTH_DEFAULT_TOKEN_STORE_TYPE: 'localStorage'\n\n  };\n\n  c.getUrl = function(key) {\n    return this.ENDPOINT_PREFIX + this[key];\n  };\n\n  c.getSocialLoginConfiguration = function(key) {\n    var canonicalKey = key ? key.toLowerCase() : '';\n    return this.SOCIAL_LOGIN_OPTIONS[canonicalKey] || {};\n  };\n  return c;\n})());\n"
  },
  {
    "path": "src/stormpath.emailverification.js",
    "content": "'use strict';\n\nangular.module('stormpath')\n\n.controller('SpEmailVerificationCtrl', ['$scope','$location','$user',function ($scope,$location,$user) {\n  $scope.showVerificationError = false;\n  $scope.verifying = false;\n  $scope.reVerificationSent = false;\n  $scope.needsReVerification = false;\n  $scope.resendFailed = false;\n  $scope.formModel = {\n    username: ''\n  };\n  if($location.search().sptoken){\n    $scope.verifying = true;\n    $user.verify($location.search().sptoken)\n      .then(function(){\n        $scope.verified = true;\n      })\n      .catch(function(){\n        $scope.needsReVerification = true;\n        $scope.showVerificationError = true;\n      })\n      .finally(function(){\n        $scope.verifying = false;\n      });\n  }else{\n    $scope.needsReVerification = true;\n    $scope.showVerificationError = true;\n  }\n  $scope.submit = function(){\n    $scope.posting = true;\n    $scope.resendFailed = false;\n    $scope.showVerificationError = false;\n    $user.resendVerificationEmail({login: $scope.formModel.username})\n      .then(function(){\n        $scope.reVerificationSent = true;\n      })\n      .catch(function(){\n        $scope.resendFailed = true;\n      }).finally(function(){\n        $scope.posting = false;\n      });\n  };\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spEmailVerification:spEmailVerification\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n * @description\n *\n * Use this directive on the page that users land on when they click an email verification link.\n * These links are sent after a user registers, see\n * {@link stormpath.spRegistrationForm:spRegistrationForm spRegistrationForm}.\n *\n * This directive will render a view that does the following:\n * * Verifies that the current URL has an `sptoken` in it.  Shows an error if not.\n * * Verifies the given `sptoken` with Stormpath, then:\n *   * If the token is valid, tell the user that the confirmation is complete and prompt the user to login.\n *   * If the token is invalid (it is expired or malformed), we prompt the user to enter\n *     their email address, so that we can try sending them a new link.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-email-verification></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-email-verification template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spEmailVerification',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spEmailVerification.tpl.html';\n    },\n    controller: 'SpEmailVerificationCtrl'\n  };\n});\n"
  },
  {
    "path": "src/stormpath.login.js",
    "content": "'use strict';\n\nangular.module('stormpath')\n\n.controller('SpLoginFormCtrl', ['$scope','$auth','$viewModel',function ($scope,$auth,$viewModel) {\n  $scope.viewModel = null;\n\n  $viewModel.getLoginModel().then(function (model) {\n\n    model.accountStores = model.accountStores.filter(function (accountStore) {\n      return accountStore.authorizeUri && accountStore.authorizeUri !== null;\n    });\n\n    $scope.viewModel = model;\n  }).catch(function (err) {\n    throw new Error('Could not load login view model from back-end: ' + err.message);\n  });\n\n  $scope.formModel = {};\n  $scope.posting = false;\n  $scope.submit = function(){\n    $scope.posting = true;\n    $scope.error = null;\n    $auth.authenticate($scope.formModel)\n      .catch(function(err){\n        $scope.posting = false;\n        $scope.error = err.message;\n      });\n  };\n}])\n\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spLoginForm:spLoginForm\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n * @description\n *\n * This directive will render a pre-built login form with all\n * the necessary fields.  After the login is a success, the following\n * will happen:\n *\n * * The {@link stormpath.authService.$auth#events_$authenticated $authenticated} event will\n * be fired.\n * *  If you have configured the {@link stormpath.$stormpath#methods_uiRouter UI Router Integration},\n * the following can happen:\n *  * The user is sent back to the view they originally requested.\n *  * The user is sent to a default view of your choice.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-login-form></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-login-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spLoginForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spLoginForm.tpl.html';\n    },\n    controller: 'SpLoginFormCtrl'\n  };\n});\n"
  },
  {
    "path": "src/stormpath.oauth.js",
    "content": "'use strict';\n\n/**\n* @ngdoc overview\n*\n* @name stormpath.oauth\n*\n* @description\n*\n* This module provides the {@link stormpath.oauth.StormpathOAuth StormpathOAuth}\n* and {@link stormpath.oauth.StormpathOAuthToken StormpathOAuthToken} services,\n* implementing a client-side OAuth2 workflow.\n*/\nangular.module('stormpath.oauth', ['stormpath.CONFIG', 'stormpath.utils', 'storpath.tokenStore'])\n\n/**\n* @ngdoc service\n*\n* @name stormpath.oauth.StormpathOAuthTokenProvider\n* @requires stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n* @description\n*\n* Provides the {@link stormpath.oauth.StormpathOAuthToken StormpathOAuthToken}\n* service.\n*/\n.provider('StormpathOAuthToken', ['STORMPATH_CONFIG',\nfunction StormpathOAuthTokenProvider(STORMPATH_CONFIG) {\n  var self = this;\n\n  this._tokenStoreType = STORMPATH_CONFIG.OAUTH_DEFAULT_TOKEN_STORE_TYPE;\n\n  /**\n  * @ngdoc method\n  * @name stormpath.oauth.StormpathOAuthTokenProvider#setTokenStoreType\n  * @methodOf stormpath.oauth.StormpathOAuthTokenProvider\n  *\n  * @param {String} tokenStoreType The name of the token store type the tokens should use to record and read their data.\n  *\n  * @description\n  *\n  * Sets the name of the token store type that the tokens use to store and load its data.\n  * See {@link stormpath.tokenStore.TokenStoreManager#getTokenStore TokenStoreManager.getTokenStore}\n  * for details.\n  */\n  this.setTokenStoreType = function setTokenStoreType(tokenStoreType) {\n    this._tokenStoreType = tokenStoreType;\n  };\n\n  /**\n  * @ngdoc service\n  * @name stormpath.oauth.StormpathOAuthToken\n  * @requires $q\n  * @requires stormpath.tokenStore.TokenStoreManager\n  *\n  * @description\n  *\n  * A service for managing OAuth tokens. It offers a simple interface for storing\n  * and reading tokens into a generic storage (backed by\n  * {@link stormpath.tokenStore.TokenStoreManager TokenStoreManager}), as well\n  * as utility methods for getting specific components of the token - the access\n  * token, refresh token, token type, as well as the Authorization header\n  * constructed from the token.\n  *\n  * It uses the token store type set in the provider, unless overrided via\n  * {@link stormpath.oauth.StormpathOAuthToken#setTokenStoreType StormpathOAuthToken.setTokenStoreType}.\n  */\n  this.$get = function $get($q, $normalizeObjectKeys, TokenStoreManager, $injector) {\n    function StormpathOAuthToken() {\n      this.tokenStore = TokenStoreManager.getTokenStore(self._tokenStoreType);\n    }\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#setTokenStoreType\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    * @param {String} tokenStoreType The name of the token store type this token should use to record and read their data.\n    *\n    * @description\n    *\n    * Sets the name of the token store type that this token uses to store and load its data.\n    * See {@link stormpath.tokenStore.TokenStoreManager#getTokenStore TokenStoreManager.getTokenStore}\n    * for details.\n    */\n    StormpathOAuthToken.prototype.setTokenStoreType = function setTokenStoreType(tokenStoreType) {\n      this.tokenStore = TokenStoreManager.getTokenStore(tokenStoreType);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#setToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    * @param {Object} token The OAuth authorization response returned by the API\n    * @returns {Promise} A promise that is resolved or rejected when the storage attempt succeeds or fails\n    *\n    * @description\n    *\n    * Stores the OAuth token data object into storage, relying on its token store\n    * for the storage implementation details. It transforms the snake-cased keys\n    * returned from the API into camel-cased keys when storing the token.\n    */\n    StormpathOAuthToken.prototype.setTokenResponse = function setTokenResponse(token) {\n      var canonicalToken = $normalizeObjectKeys(token);\n      // Store a time at which we should renew the token, subtract off one second to give us some buffer of time\n      canonicalToken.exp = new Date(new Date().setMilliseconds(0)+((token.expires_in-1)*1000));\n      return this.tokenStore.put(STORMPATH_CONFIG.OAUTH_TOKEN_STORAGE_NAME, canonicalToken);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} A promise containing either the resolved token, or a rejection with a reason.\n    *\n    * @description\n    *\n    * Retrieves the OAuth token data object from storage, relying on its set token\n    * store for the loading implementation details. The result will use camel-cased\n    * keys, as noted in\n    * {@link stormpath.oauth.StormpathOAuthToken#setTokenResponse StormpathOAuthToken.setTokenResponse}.\n    */\n    StormpathOAuthToken.prototype.getTokenResponse = function getTokenResponse() {\n      return this.tokenStore.get(STORMPATH_CONFIG.OAUTH_TOKEN_STORAGE_NAME);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#removeToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} A promise indicating whether the operation had succeeded\n    *\n    * @description\n    *\n    * Removes the OAuth token from storage, relying on its set token store for the\n    * implementation details.\n    */\n    StormpathOAuthToken.prototype.removeToken = function removeToken() {\n      return this.tokenStore.remove(STORMPATH_CONFIG.OAUTH_TOKEN_STORAGE_NAME);\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getAccessToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} Promise containing the access token, or a rejection in case of failure\n    *\n    * @description\n    *\n    * Retrieves the access token from storage, relying on the token store for implementation.\n    * In case there of storage failure or there being no access token, the result is instead\n    * a rejected promise.\n    */\n    StormpathOAuthToken.prototype.getAccessToken = function getAccessToken() {\n      var self = this;\n      return this.getTokenResponse()\n        .then(function(token) {\n          var tokenType = token && token.tokenType;\n          var accessToken = token && token.accessToken;\n\n          if (!tokenType || !accessToken) {\n            return $q.reject();\n          }\n\n          if (new Date() >= new Date(token.exp)) {\n            var StormpathOAuth = $injector.get('StormpathOAuth');\n            return StormpathOAuth.refresh().then(function(){\n              return self.getAccessToken();\n            });\n          }\n\n          return accessToken;\n        });\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getRefreshToken\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} Promise containing the refresh token, or a rejection in case of failure\n    *\n    * @description\n    *\n    * Retrieves the refresh token from storage, relying on the token store for implementation.\n    * In case there of storage failure or there being no refresh token, the result is instead\n    * a rejected promise.\n    */\n    StormpathOAuthToken.prototype.getRefreshToken = function getRefreshToken() {\n      return this.getTokenResponse().then(function(token) {\n        if (token) {\n          return token.refreshToken;\n        }\n\n        return $q.reject();\n      });\n    };\n\n    /**\n    * @ngdoc method\n    * @name stormpath.oauth.StormpathOAuthToken#getTokenType\n    * @methodOf stormpath.oauth.StormpathOAuthToken\n    *\n    * @returns {Promise} Promise containing the token type, or a rejection in case of failure\n    *\n    * @description\n    *\n    * Retrieves the token type from storage, relying on the token store for implementation.\n    * In case there of storage failure or there being no token type, the result is instead\n    * a rejected promise.\n    */\n    StormpathOAuthToken.prototype.getTokenType = function getTokenType() {\n      return this.getTokenResponse().then(function(token) {\n        if (token) {\n          return token.tokenType;\n        }\n\n        return $q.reject();\n      });\n    };\n\n    return new StormpathOAuthToken();\n  };\n\n  this.$get.$inject = ['$q', '$normalizeObjectKeys', 'TokenStoreManager', '$injector'];\n}])\n\n/**\n* @ngdoc service\n*\n* @name stormpath.oauth.StormpathOAuthProvider\n* @requires stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG\n* @description\n*\n* Provides the {@link stormpath.oauth.StormpathOAuth StormpathOAuth}\n* service.\n*/\n.provider('StormpathOAuth', ['STORMPATH_CONFIG', function StormpathOAuthProvider(STORMPATH_CONFIG) {\n\n  var oauthInstance;\n\n  /**\n  * @ngdoc service\n  * @name stormpath.oauth.StormpathOAuth\n  * @requires $q\n  * @requires stormpath.oauth.StormpathOAuthToken\n  *\n  * @description\n  *\n  * A service for managing the OAuth client-side authentication flow logic. It\n  * offers methods for authenticating via the `password` grant type, refreshing\n  * access tokens via refresh tokens, and revoking the current token.\n  */\n  this.$get = function($http, $spFormEncoder, StormpathOAuthToken) {\n    function StormpathOAuth() {\n      this.refreshPromise = null;\n      return this;\n    }\n\n    /**\n    * @ngdoc method\n    * @methodOf stormpath.oauth.StormpathOAuth\n    * @name #authenticate\n    *\n    *\n    * @param {Object} requestData Authentication data object. Expects an email/username and a password field.\n    * @param {Object=} opts Additional request options, (e.g. headers), optional.\n    *\n    * @returns {Promise} A promise containing the authentication response\n    *\n    * @description\n    *\n    * Attempts to authenticate the user, using the password grant flow by default,\n    * although the method can be overriden via the `requestOpts` parameter. If\n    * successful, automatically stores the token using\n    * {@link stormpath.oauth.StormpathOAuthToken#setTokenResponse StormpathOAuthToken.setTokenResponse}.\n    */\n    StormpathOAuth.prototype.authenticate = function authenticate(requestData, extraHeaders) {\n      var self = this;\n      var data = angular.extend({\n        grant_type: 'password'\n      }, requestData);\n\n      var headers = angular.extend({\n        Accept: 'application/json'\n      }, extraHeaders);\n\n      return $http($spFormEncoder.formPost({\n        url: STORMPATH_CONFIG.getUrl('OAUTH_AUTHENTICATION_ENDPOINT'),\n        method: 'POST',\n        headers: headers,\n        data: data\n      })).then(function(response) {\n        StormpathOAuthToken.setTokenResponse(response.data);\n\n        return response;\n      });\n    };\n\n    /**\n    * @ngdoc method\n    * @methodOf stormpath.oauth.StormpathOAuth\n    * @name revoke\n    *\n    * @returns {Promise} A promise containing the revokation response\n    *\n    * @description\n    *\n    * Attempts to revoke the currently active token. If successful, also removes\n    * the token from storage, using\n    * {@link stormpath.oauth.StormpathOAuthToken#removeToken StormpathOAuthToken.removeToken}.\n    * This method is specific to an OAuth workflow, `$auth.endSession()` should be used instead\n    * as it is generc and defers to this method when nedeed.\n    */\n    StormpathOAuth.prototype.revoke = function revoke() {\n\n      return StormpathOAuthToken.getTokenResponse().then(function(token) {\n        var data = {\n          token: token.refreshToken || token.accessToken,\n          token_type_hint: token.refreshToken ? 'refresh_token' : 'access_token'\n        };\n\n        return $http($spFormEncoder.formPost({\n          url: STORMPATH_CONFIG.getUrl('OAUTH_REVOKE_ENDPOINT'),\n          method: 'POST',\n          data: data\n        })).finally(function(response) {\n          StormpathOAuthToken.removeToken();\n\n          return response;\n        });\n      });\n    };\n\n    /**\n     * @ngdoc method\n    * @methodOf stormpath.oauth.StormpathOAuth\n    * @name refresh\n    *\n    * @param {Object=} requestData Additional data to add to the refresh POST request, optional.\n    * @param {Object=} opts Additional request options, (e.g. headers), optional.\n    *\n    * @returns {Promise} A promise containing the refresh attempt response\n    *\n    * @description\n    *\n    * Attempts to refresh the current token, using its refresh token. If successful,\n    * updates the currently stored token using\n    * {@link stormpath.oauth.StormpathOAuthToken#setTokenResponse StormpathOAuthToken.setTokenResponse}\n    * with the response data.\n    */\n    StormpathOAuth.prototype.refresh = function(requestData, extraHeaders) {\n\n      var self = this;\n\n      if (self.refreshPromise) {\n        return self.refreshPromise;\n      }\n\n      return self.refreshPromise = StormpathOAuthToken.getRefreshToken().then(function(refreshToken) {\n        var data = angular.extend({\n          grant_type: 'refresh_token',\n          refresh_token: refreshToken\n        }, requestData);\n\n        var headers = angular.extend({\n          Accept: 'application/json'\n        }, extraHeaders);\n\n        return $http($spFormEncoder.formPost({\n          url: STORMPATH_CONFIG.getUrl('OAUTH_AUTHENTICATION_ENDPOINT'),\n          method: 'POST',\n          headers: headers,\n          data: data\n        })).then(function(response) {\n          StormpathOAuthToken.setTokenResponse(response.data);\n          return response;\n        }).catch(function(response){\n          StormpathOAuthToken.removeToken();\n          return response;\n        }).finally(function (){\n          self.refreshPromise = null;\n        });\n      });\n    };\n\n    if (!oauthInstance) {\n      oauthInstance = new StormpathOAuth();\n    }\n\n    return oauthInstance;\n  };\n\n  this.$get.$inject = ['$http', '$spFormEncoder', 'StormpathOAuthToken'];\n}])\n\n/**\n* @ngdoc service\n* @name stormpath.utils.StormpathOAuthInterceptor\n*\n* @description\n*\n* Processes requests and response errors to avoid manual OAuth flow integration.\n* Adds property Authorization headers to outgoing requests to external domains\n* and handles specific OAuth-based response errors.\n*/\n.factory('StormpathOAuthInterceptor', ['$isCurrentDomain', '$rootScope', '$q', '$injector', 'StormpathOAuthToken', 'STORMPATH_CONFIG',\nfunction($isCurrentDomain, $rootScope, $q, $injector, StormpathOAuthToken, STORMPATH_CONFIG) {\n\n  function StormpathOAuthInterceptor() {}\n\n  /**\n  * @ngdoc method\n  * @name stormpath.utils.StormpathOAuthInterceptor#request\n  * @methodOf stormpath.utils.StormpathOAuthInterceptor\n  *\n  * @param {Object} config $http config object.\n  * @return {Promise} config Promise containing $http config object.\n  *\n  * @description\n  *\n  * Adds the Authorization header on all outgoing request that are going to a\n  * different domain, if the match an expression in the  AUTO_AUTHORIZED_URIS list.\n  */\n\n  StormpathOAuthInterceptor.prototype.request = function request(config) {\n\n    if (STORMPATH_CONFIG.AUTO_AUTHORIZED_URIS.some(function(expr){\n      var regex = expr instanceof RegExp ? expr : new RegExp(expr);\n      return regex.test(config.url);\n    })) {\n      return StormpathOAuthToken.getAccessToken()\n        .then(function(token){\n          config.headers.Authorization = 'Bearer ' + token;\n          return config;\n        }).catch(function(){\n          return config;\n        });\n    }\n\n    return config;\n  };\n\n  return new StormpathOAuthInterceptor();\n}])\n.config(['$httpProvider', function($httpProvider) {\n  $httpProvider.interceptors.push('StormpathOAuthInterceptor');\n}]);\n"
  },
  {
    "path": "src/stormpath.passwordreset.js",
    "content": "'use strict';\n\nangular.module('stormpath')\n.controller('SpPasswordResetRequestCtrl', ['$scope','$user',function ($scope,$user) {\n  $scope.sent = false;\n  $scope.posting = false;\n  $scope.formModel = {\n    username: ''\n  };\n  $scope.error = null;\n  $scope.submit = function(){\n    $scope.posting = true;\n    $scope.error = null;\n    $user.passwordResetRequest({email: $scope.formModel.email})\n      .then(function(){\n        $scope.sent = true;\n      })\n      .catch(function(err){\n        $scope.error = err.message;\n      }).finally(function(){\n        $scope.posting = false;\n      });\n  };\n}])\n\n.controller('SpPasswordResetCtrl', ['$scope','$location','$user',function ($scope,$location,$user) {\n  var sptoken = $location.search().sptoken;\n  $scope.showVerificationError = false;\n  $scope.verifying = false;\n  $scope.verified = false;\n  $scope.posting = false;\n  $scope.reset = false;\n  $scope.error = null;\n\n  $scope.resendFailed = false;\n  $scope.formModel = {\n    password: '',\n    confirmPassword: ''\n  };\n\n  if(typeof sptoken==='string'){\n    $scope.verifying = true;\n    $user.verifyPasswordResetToken(sptoken)\n      .then(function(){\n        $scope.verified = true;\n      })\n      .catch(function(){\n        $scope.showVerificationError = true;\n      })\n      .finally(function(){\n        $scope.verifying = false;\n      });\n  }else{\n    $scope.showVerificationError = true;\n  }\n  $scope.submit = function(){\n    if($scope.formModel.password!==$scope.formModel.confirmPassword){\n      $scope.error = 'Passwords do not match';\n      return;\n    }\n    $scope.posting = true;\n    $scope.error = null;\n    $scope.showVerificationError = false;\n    $user.resetPassword(sptoken, {password: $scope.formModel.password})\n      .then(function(){\n        $scope.reset = true;\n      })\n      .catch(function(err){\n        $scope.error = err.message;\n      }).finally(function(){\n        $scope.posting = false;\n      });\n  };\n\n}])\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spPasswordResetRequestForm:spPasswordResetRequestForm\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n * @description\n *\n * This directive will render a pre-built form which prompts the user for their\n * username/email.  If an account is found, we will send them an email with a\n * password reset link.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-password-reset-request-form></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-password-reset-request-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spPasswordResetRequestForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spPasswordResetRequestForm.tpl.html';\n    },\n    controller: 'SpPasswordResetRequestCtrl'\n  };\n})\n/**\n * @ngdoc directive\n *\n * @name stormpath.spPasswordResetForm:spPasswordResetForm\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n *\n * @description\n *\n * Use this directive on the page that users land on when they click on a password\n * reset link.  To send users a password reset link, see\n * {@link stormpath.spPasswordResetRequestForm:spPasswordResetRequestForm spPasswordResetRequestForm}.\n *\n * This directive will render a password reset form that does the following:\n * * Verifies that the current URL has an `sptoken` in it.  Shows an error if not.\n * * Verifies the given `sptoken` with Stormpath, then:\n *   * If the token is valid, shows a form that allows the user to enter a new password.\n *   * If the token is invalid (it is expired or malformed), we prompt the user to enter\n *     their email address, so that we can try sending them a new link.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-password-reset-form></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-password-reset-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spPasswordResetForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spPasswordResetForm.tpl.html';\n    },\n    controller: 'SpPasswordResetCtrl'\n  };\n});\n"
  },
  {
    "path": "src/stormpath.registration.js",
    "content": "'use strict';\n\nangular.module('stormpath')\n.controller('SpRegistrationFormCtrl', ['$scope','$user','$auth','$location','$viewModel','$injector', function ($scope,$user,$auth,$location,$viewModel, $injector) {\n  $scope.formModel = (typeof $scope.formModel==='object') ? $scope.formModel : {};\n  $scope.created = false;\n  $scope.enabled = false;\n  $scope.creating = false;\n  $scope.authenticating = false;\n  $scope.viewModel = null;\n\n  $viewModel.getRegisterModel().then(function (model) {\n\n    model.accountStores = model.accountStores.filter(function (accountStore) {\n      return accountStore.authorizeUri && accountStore.authorizeUri !== null;\n    });\n\n    $scope.viewModel = model;\n  }).catch(function (err) {\n    throw new Error('Could not load login view model from back-end: ' + err.message);\n  });\n\n  $scope.submit = function(){\n    $scope.creating = true;\n    $scope.error = null;\n    $user.create($scope.formModel)\n      .then(function(account){\n        $scope.created = true;\n        $scope.enabled = account.status === 'ENABLED';\n        if($scope.enabled && $scope.autoLogin){\n          $scope.authenticating = true;\n          $auth.authenticate({\n            username: $scope.formModel.email,\n            password: $scope.formModel.password\n          })\n          .then(function(){\n            var $state = $injector.has('$state') ? $injector.get('$state') : null;\n            if($scope.postLoginState && $state){\n              $state.go($scope.postLoginState);\n            }\n            else if($scope.postLoginPath){\n              $location.path($scope.postLoginPath);\n            }\n          })\n          .catch(function(err){\n            $scope.error = err.message;\n          })\n          .finally(function(){\n            $scope.authenticating = false;\n            $scope.creating = false;\n          });\n        }else{\n          $scope.creating = false;\n        }\n      })\n      .catch(function(err){\n        $scope.creating = false;\n        $scope.error = err.message;\n      });\n  };\n}])\n\n\n/**\n * @ngdoc directive\n *\n * @name stormpath.spRegistrationForm:spRegistrationForm\n *\n * @param {boolean} autoLogin\n *\n * Default `false`. Automatically authenticate the user\n * after creation.  This makes a call to\n * {@link stormpath.authService.$auth#methods_authenticate $auth.authenticate}, which will\n * trigger the event {@link stormpath.authService.$auth#events_$authenticated $authenticated}.\n * This is not possible if the email verification workflow is enabled on the directory that\n * the account is created in.\n *\n * @param {string} postLoginState\n *\n * If using the `autoLogin` option, you can specify the name of a UI state that the user\n * should be redirected to after they successfully have registered.  This is a UI Router\n * integration, and requires that module.\n *\n * @param {string} postLoginPath\n *\n * If using the `autoLogin` option, you can specify the path that the user\n * should be sent to after registration.  This value is passed to\n * `$location.path()` and does not require a specific routing module.\n *\n * @param {string} template-url\n *\n * An alternate template URL if you want\n * to use your own template for the form.\n *\n *\n * @description\n *\n * This directive will render a pre-built user registration form with the following\n * fields:\n *  * First Name\n *  * Last Name\n *  * Email\n *  * Password\n *\n * # Customizing the Form Fields\n *\n * Our library will make a JSON GET request to the `/register` endpoint on your\n * server, and it expects to receive a view model that describes the form and\n * it's fields.  As such, you will define your custom registration fields in\n * your server-side configuration.  Please see the relevant documentation:\n *\n * * Node.js: [Express-Stormpath - Registration](https://docs.stormpath.com/nodejs/express/latest/registration.html)\n * * PHP: [Stormpath Laravel - Registration](https://docs.stormpath.com/php/laravel/latest/registration.html)\n * * All other frameworks: please see the server integration guide or contact\n *   [support@stormpath.com](support@stormpath.com) for assistance.\n *\n * # Customizing the Form Template\n *\n * If you would like to modify the HTML template that renders our form, you can\n * do that as well.  Here is what you'll need to do:\n *\n * * Create a new view file in your application.\n * * Copy our default template HTML code into your file, found here:\n * <a href=\"https://github.com/stormpath/stormpath-sdk-angularjs/blob/master/src/spRegistrationForm.tpl.html\" target=\"_blank\">spRegistrationForm.tpl.html</a>.\n * * Modify the template to fit your needs, making sure to use `formModel.<FIELD>` as the\n * value for `ng-model` where `.<FIELD>` is the name of the field you want to set on\n * the new account (such as `middleName`).\n * * Use the `template-url` option on the directive to point to your new view file.\n *\n * Any form fields you supply that are not one of the default fields (first\n * name, last name) will need to be defined in the view model (see above) and\n * will be automatically placed into the new account's customa data object.\n *\n * # Email Verification\n *\n * If you are using the email verification workflow, the default template has a message,\n * which will be shown to the user, telling them that they need to check their email\n * for verification.\n *\n * If you are NOT using the email verification workflow, you can, optionally,\n * automatically login the user and redirect them to a UI state in your application.\n * See the options below.\n *\n * # Server Interaction\n *\n * This directive makes a call to\n * {@link stormpath.userService.$user#methods_create $user.create()}\n * when it is ready to POST the form to the server. Please see that method\n * for more information.\n *\n * @example\n *\n * <pre>\n * <!-- If you want to use the default template -->\n * <div class=\"container\">\n *   <div sp-registration-form post-login-state=\"main\"></div>\n * </div>\n *\n * <!-- If you want to use your own template -->\n * <div class=\"container\">\n *   <div sp-registration-form template-url=\"/path/to/my-custom-template.html\"></div>\n * </div>\n * </pre>\n */\n.directive('spRegistrationForm',function(){\n  return {\n    templateUrl: function(tElemenet,tAttrs){\n      return tAttrs.templateUrl || 'spRegistrationForm.tpl.html';\n    },\n    controller: 'SpRegistrationFormCtrl',\n    link: function(scope,element,attrs){\n      scope.autoLogin = attrs.autoLogin==='true';\n      scope.postLoginPath = attrs.postLoginPath || '';\n      scope.postLoginState = attrs.postLoginState || '';\n    }\n  };\n});"
  },
  {
    "path": "src/stormpath.social-login.js",
    "content": "(function() {\n  'use strict';\n\n/**\n * @ngdoc overview\n *\n * @name  stormpath.socialLoginService\n *\n * @description\n *\n * This module provides the {@link stormpath.socialLoginService.$socialLogin $socialLogin} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\n\n /**\n  * @ngdoc object\n  *\n  * @name stormpath.socialLoginService.$socialLogin\n  *\n  * @description\n  *\n  * The social login service provides a generic authorization interface through\n  * the Stormpath social login interface.\n  */\n  function SocialLoginService(STORMPATH_CONFIG, $encodeQueryParams, $getLocalUrl, $http, $window) {\n    this.providersPromise = null;\n    this.STORMPATH_CONFIG = STORMPATH_CONFIG;\n    this.$encodeQueryParams = $encodeQueryParams;\n    this.$getLocalUrl = $getLocalUrl;\n    this.$http = $http;\n    this.$window = $window;\n  }\n\n  /**\n  * @ngdoc method\n  *\n  * @name authorize\n  * @methodOf stormpath.socialLoginService.$socialLogin\n  * @description\n  *\n  * Authorizes the user using a social authentication provider. This method starts\n  * the redirect flow that attempts to authenticate the user, and, if successful,\n  * ends in the redirect uri configured via {@link STORMPATH_CONFIG.SOCIAL_LOGIN_REDIRECT_URI}.\n  *\n  * @param {String} accountStoreHref\n  * The HREF of the account store (directory) that is set up to provide the social\n  * authentication service.\n  *\n  * @param {Object} options\n  * Additional options (query parameters) to send with the authentication request.\n  *\n  */\n  SocialLoginService.prototype.authorize = function(accountStore, options) {\n    var requestParams = angular.extend({\n      response_type: this.STORMPATH_CONFIG.SOCIAL_LOGIN_RESPONSE_TYPE,\n      account_store_href: accountStore.href,\n      redirect_uri: this.$getLocalUrl(this.STORMPATH_CONFIG.SOCIAL_LOGIN_REDIRECT_URI)\n    }, options);\n\n    var queryParams = this.$encodeQueryParams(requestParams);\n    var socialAuthUri = accountStore.authorizeUri + queryParams;\n\n    this.$window.location = socialAuthUri;\n  };\n\n  angular.module('stormpath.socialLogin', ['stormpath.CONFIG', 'stormpath.utils'])\n\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.socialLoginService.$socialLoginProvider\n   *\n   * @description\n   *\n   * Provides the {@link stormpath.socialLoginService.$socialLogin $socialLogin} service.\n   *\n   * Currently, this provider does not have any configuration methods.\n   */\n  .config(['$injector', 'STORMPATH_CONFIG', function $socialLoginProvider($injector, STORMPATH_CONFIG) {\n    var socialLoginFactory = ['$encodeQueryParams', '$http', '$window', '$getLocalUrl', function socialLoginFactory($encodeQueryParams, $http, $window, $getLocalUrl) {\n      return new SocialLoginService(STORMPATH_CONFIG, $encodeQueryParams, $getLocalUrl, $http, $window);\n    }];\n\n    $injector.get('$provide').factory(STORMPATH_CONFIG.SOCIAL_LOGIN_SERVICE_NAME, socialLoginFactory);\n  }])\n\n  /**\n   * @ngdoc directive\n   *\n   * @name stormpath.spSocialLogin:spSocialLogin\n   *\n   * @description\n   *\n   * Add this directive to a button or link in order to authenticate using a social provider.\n   * The value should be the account store HREF a social provider, such as Google or Facebook.\n   *\n   * The `sp-name` field must be set to the provider ID of the corresponding provider, e.g.\n   * `google` or `facebook`.\n   *\n   * Any additional fields can be specified as an object, via the `sp-options` field. These\n   * options will additionally be augmented (and overriden) by the options set for the given\n   * provider (determined by value of `sp-name`) in {@link STORMPATH_CONFIG.SOCIAL_LOGIN_OPTIONS}.\n   *\n   * {@link http://docs.stormpath.com/guides/social-integrations/}\n   *\n   * @example\n   *\n   * <pre>\n   * <div class=\"container\">\n   *   <button sp-social-login=\"http://url.example/facebook-href\" sp-name=\"facebook\" sp-options=\"{scope: 'email'}\">Login with Facebook</button>\n   * </div>\n   * </pre>\n   */\n  .directive('spSocialLogin', ['$viewModel', '$auth', '$http', '$injector', 'STORMPATH_CONFIG', function($viewModel, $auth, $http, $injector, STORMPATH_CONFIG) {\n    return {\n      link: function(scope, element, attrs) {\n        var accountStore = scope.$eval(attrs.spSocialLogin);\n        var blacklist = ['href', 'providerId', 'clientId'];\n        var social = $injector.get(STORMPATH_CONFIG.SOCIAL_LOGIN_SERVICE_NAME);\n\n        scope.providerName = accountStore.provider.providerId;\n\n        element.bind('click', function() {\n\n          var cleanOptions = {};\n\n          angular.forEach(accountStore.provider, function(value, key) {\n            if (value && blacklist.indexOf(key) !== -1) {\n              cleanOptions[key] = value;\n            }\n          });\n\n          cleanOptions = angular.extend(\n            cleanOptions,\n            STORMPATH_CONFIG.getSocialLoginConfiguration(accountStore.provider.providerId)\n          );\n\n          social.authorize(accountStore, cleanOptions);\n        });\n      }\n    };\n  }])\n\n  /**\n  * @private\n  *\n  * @ngdoc service\n  * @name stormpath.socialLogin.$processSocialAuthToken\n  * @description\n  *\n  * Executes the flow for processing social authentication tokens returned from\n  * the social login authentication redirect flow. If the token is present, it\n  * is used to authenticate the user using the `stormpath_token` grant type.\n  *\n  * Appropriate authentication success or failure events are broadcast when the\n  * authentication concludes.\n  *\n  * If the token is not present in the URL query parameters, the function returns\n  * a resolved promise immediatelly.\n  */\n  .factory('$processSocialAuthToken', ['STORMPATH_CONFIG', '$parseUrl', '$window', '$injector', '$q', '$rootScope',\n    function(STORMPATH_CONFIG, $parseUrl, $window, $injector, $q, $rootScope) {\n      return function processSocialAuthToken() {\n        var parsedUrl = $parseUrl($window.location.href);\n\n        // If this field is present, this means that we have been redirected here\n        // from a social login flow\n        if (parsedUrl.search.jwtResponse) {\n          var AuthService = $injector.get(STORMPATH_CONFIG.AUTH_SERVICE_NAME);\n          return AuthService.authenticate({\n            grant_type: 'stormpath_token',\n            token: parsedUrl.search.jwtResponse\n          }).then(function() {\n            // Clears the URL of the token in both hashbang and HTML5 mode\n            $window.location.search = '';\n\n            $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_SUCCESS_EVENT_NAME)\n          }).catch(function(err) {\n            $rootScope.$broadcast(STORMPATH_CONFIG.AUTHENTICATION_FAILURE_EVENT_NAME);\n            throw err;\n          });\n        }\n\n        return $q.resolve();\n      };\n    }]);\n}());\n"
  },
  {
    "path": "src/stormpath.tokenStore.js",
    "content": "'use strict';\n\n/**\n* @ngdoc overview\n*\n* @name stormpath.tokenStore\n*\n* @description\n*\n* This module provides a global access point for registering and fetching token\n* store mechanisms, as used by the {@link stormpath.oauth} module.\n*/\n\n/**\n* @ngdoc object\n* @interface\n* @name stormpath.tokenStore.TokenStore\n*\n* @description\n* A token store implementation. It allows simple key-value pair storing, fetching,\n* and deleting. Its methods may be synchronous, but must always return promises.\n*/\n\n/**\n* @ngdoc method\n* @name stormpath.tokenStore.TokenStore#put\n* @methodOf stormpath.tokenStore.TokenStore\n*\n* @param {String} name The name under which to store a value.\n* @param {Any} value The string representation of a value.\n* @returns {Promise} Indication of success\n*\n* @description\n*\n* Stores a string value in a key-value store.\n*/\n\n/**\n* @ngdoc method\n* @name stormpath.tokenStore.TokenStore#get\n* @methodOf stormpath.tokenStore.TokenStore\n*\n* @param {String} name The name for which to retrieve a value.\n* @returns {Promise} The resolved value retrieved from the store, or a rejection with a reason.\n*\n* @description\n*\n* Retrieves a value from a key-value store.\n*/\n\n/**\n* @ngdoc method\n* @name stormpath.tokenStore.TokenStore#remove\n* @methodOf stormpath.tokenStore.TokenStore\n*\n* @param {String} name The name for which to remove a value.\n* @returns {Promise} Indication of success. Should resolve if there is no value to remove.\n*\n* @description\n*\n* Remove a value from a key-value store.\n*/\n\nangular.module('storpath.tokenStore', ['stormpath.CONFIG'])\n\n/**\n* @ngdoc service\n*\n* @name stormpath.tokenStore.TokenStoreManagerProvider\n*\n* @description\n*\n* Provides the {@link stormpath.tokenStore.TokenStoreManager TokenStoreManager} service.\n*/\n.provider('TokenStoreManager', function() {\n  var tokenStores = {};\n\n  /**\n  * @ngdoc object\n  *\n  * @name stormpath.tokenStore.TokenStoreManager\n  *\n  * @description\n  *\n  * This service provides methods for registering token stores (with duck-typed\n  * validation), as well as retrieving them by name.\n  *\n  * Token store implementations must implement the\n  * {@link stormpath.tokenStore.TokenStore TokenStore interface}.\n  *\n  * All token stores are expected to satisfy the following contract:\n  *   - Instances must have a `put` method that takes a key and a value, stores them, and returns a promise indicating success\n  *   - Instances must have a `get` method that takes a key and returns a promise containing the value for the given key, or a rejection with a reason\n  *   - Instances must have a `remove` method that takes a key and removes the value, returning the result as a promise\n  *\n  * See {@link stormpath.tokenStore.LocalStorageTokenStore LocalStorageTokenStore}\n  * for an example of an implementation.\n  *\n  * @example\n  *\n  * <pre>\n  *   angular.module('app')\n  *     .run(['$q', 'TokenStoreManager', function($q, TokenStoreManager) {\n  *       // Can also be provided by a service/factory for better code organisation\n  *       var myStore = {\n  *         data: {},\n  *         get: function get(key) {\n  *           return this.data[key] ? $q.resolve(this.data[key]) : $q.reject();\n  *         },\n  *         put: function put(key, value) {\n  *           this.data[key] = value;\n  *           return $q.resolve();\n  *         },\n  *         remove: function remove(key) {\n  *           delete this.data[key];\n  *           return $q.resolve();\n  *         }\n  *       };\n  *\n  *       TokenStoreManager.registerTokenStore('basicStore', myStore);\n  *\n  *       var alsoMyStore = TokenStoreManager.getTokenStore('basicStore');\n  *     }]);\n  * </pre>\n  */\n  this.$get = function $get() {\n    return {\n      /**\n      * @ngdoc method\n      * @name stormpath.tokenStore.TokenStoreManager#registerTokenStore\n      *\n      * @methodOf stormpath.tokenStore.TokenStoreManager\n      *\n      * @param {String} name The name under which to store the token store implementation\n      * @param {TokenStore} tokenStore A concrete {@link stormpath.tokenStore.TokenStore TokenStore}\n      *\n      * @throws {Error} tokenStore must satisfy the token store contract methods (get, put, remove).\n      */\n      registerTokenStore: function registerTokenStore(name, tokenStore) {\n        var requiredMethods = ['get', 'put', 'remove'];\n\n        var isValid = tokenStore && requiredMethods.reduce(function(valid, method) {\n          return valid && angular.isFunction(tokenStore[method]);\n        }, true);\n\n        if (!isValid) {\n          throw new Error('Invalid token store. `get`, `put` and `remove` methods must be implemented');\n        }\n\n        tokenStores[name] = tokenStore;\n      },\n      /**\n      * @ngdoc method\n      * @name stormpath.tokenStore.TokenStoreManager#getTokenStore\n      *\n      * @methodOf stormpath.tokenStore.TokenStoreManager\n      *\n      * @param {String} name The name of the token store implementation.\n      * @returns {TokenStore} The token store implementation stored under that name\n      * @throws {Error} When no token store is present for that name.\n      */\n      getTokenStore: function getTokenStore(name) {\n        if (angular.isUndefined(tokenStores[name])) {\n          throw new Error('Unrecognised token store: ' + name);\n        }\n\n        return tokenStores[name];\n      }\n    };\n  };\n})\n\n/**\n* @ngdoc service\n* @name stormpath.tokenStore.LocalStorageTokenStore\n* @augments stormpath.tokenStore.TokenStore\n*\n* @description\n*\n* Implements token storage via browser localStorage.\n*/\n.factory('LocalStorageTokenStore', ['$q', function($q) {\n  function LocalStorageTokenStore() {\n    this._checkAvailability();\n  }\n\n  // Checks whether the current environment supports localStorage and sets the\n  // internal state accordingly\n  LocalStorageTokenStore.prototype._checkAvailability = function _checkAvailability() {\n    if (typeof localStorage === undefined) {\n      this.hasLocalStorage = false;\n    } else {\n      try {\n        localStorage.setItem('sp:feature_test', 'test');\n\n        if (localStorage.getItem('sp:feature_test') === 'test') {\n          localStorage.removeItem('sp:feature_test');\n          this.hasLocalStorage = true;\n        } else {\n          this.hasLocalStorage = false;\n        }\n      } catch (e) {\n        this.hasLocalStorage = false;\n      }\n    }\n  };\n\n  // Provides uniform rejection method for when localStorage is not supported\n  LocalStorageTokenStore.prototype._notImplementedError = function _notImplementedError() {\n    return $q.reject({\n      error: {\n        message: 'Local storage not supported in this environment'\n      }\n    });\n  };\n\n  /**\n  * @ngdoc method\n  * @name stormpath.tokenStore.LocalStorageTokenStore#put\n  * @methodOf stormpath.tokenStore.LocalStorageTokenStore\n  *\n  * @param {String} name The name under which to store a value.\n  * @param {Any} value The string representation of a value.\n  * @returns {Promise} Indication of success\n  *\n  * @description\n  *\n  * Attempts to store a key-value pair using the localStorage API.\n  */\n  LocalStorageTokenStore.prototype.put = function put(key, value) {\n    if (!this.hasLocalStorage) {\n      return this._notImplementedError();\n    }\n\n    var stringValue;\n\n    try {\n      stringValue = JSON.stringify(value);\n    } catch (e) {\n      return $q.reject(e);\n    }\n\n    localStorage.setItem(key, stringValue);\n    return $q.resolve();\n  };\n\n  /**\n  * @ngdoc method\n  * @name stormpath.tokenStore.LocalStorageTokenStore#get\n  * @methodOf stormpath.tokenStore.LocalStorageTokenStore\n  *\n  * @param {String} name The name for which to retrieve a value.\n  * @returns {Promise} Resolved with value or rejected if local storage is unsupported, or value not present.\n  *\n  * @description\n  *\n  * Attempts to retrieve a value for a given key using the localStorage API.\n  */\n  LocalStorageTokenStore.prototype.get = function get(key) {\n    if (!this.hasLocalStorage) {\n      return this._notImplementedError();\n    }\n\n    var value = localStorage.getItem(key);\n\n    if (angular.isDefined(value)) {\n      try {\n        return $q.resolve(JSON.parse(value));\n      } catch (e) {\n        return $q.reject(e);\n      }\n    }\n\n    return $q.reject(new Error('Token not found'));\n  };\n\n  /**\n  * @ngdoc method\n  * @name stormpath.tokenStore.LocalStorageTokenStore#remove\n  * @methodOf stormpath.tokenStore.LocalStorageTokenStore\n  *\n  * @param {String} name The name for which to remove the value.\n  * @returns {Promise} Indication of success\n  *\n  * @description\n  *\n  * Attempts to remove a value for a key from store using the localStorage API.\n  */\n  LocalStorageTokenStore.prototype.remove = function remove(key) {\n    if (!this.hasLocalStorage) {\n      return this._notImplementedError();\n    }\n\n    localStorage.removeItem(key);\n    return $q.resolve();\n  };\n\n  return new LocalStorageTokenStore();\n}])\n\n// Register the basic localStorage provider when run\n.run(['TokenStoreManager', 'LocalStorageTokenStore',\nfunction(TokenStoreManager, LocalStorageTokenStore) {\n  TokenStoreManager.registerTokenStore('localStorage', LocalStorageTokenStore);\n}]);\n"
  },
  {
    "path": "src/stormpath.user.js",
    "content": "'use strict';\n/**\n * @ngdoc overview\n *\n * @name stormpath.userService\n *\n * @description\n *\n * This module provides the {@link stormpath.userService.$user $user} service.\n */\n\n/**\n * @ngdoc object\n *\n * @name stormpath.userService.$userProvider\n *\n * @description\n *\n * Provides the {@link stormpath.userService.$user $user} service.\n *\n * Currently, this provider does not have any configuration methods.\n */\n\nangular.module('stormpath.userService',['stormpath.CONFIG', 'stormpath.utils', 'stormpath.socialLogin'])\n.provider('$user', [function $userProvider(){\n\n  /**\n   * @ngdoc object\n   *\n   * @name stormpath.userService.$user\n   *\n   * @description\n   *\n   * Use this service to get the current user and do access control checks\n   * on the user.\n   */\n\n  function User(data){\n    var self = this;\n    Object.keys(data).map(function(k){\n      self[k] = data[k];\n    });\n  }\n  /**\n  * This method may change in the future, do not use.\n  * Please use the `ifUserInGroup` directive instead\n  */\n  User.prototype.inGroup = function inGroup(groupName) {\n    return this.groups.items.filter(function(group){\n      return group.name === groupName;\n    }).length >0;\n  };\n  /**\n  * This method may change in the future, do not use.\n  * Please use the `ifUserInGroup` directive instead\n  */\n  User.prototype.matchesGroupExpression = function matchesGroupExpression(regex) {\n    return this.groups.items.filter(function(group){\n      return regex.test(group.name);\n    }).length >0;\n  };\n  /**\n  * This method may change in the future, do not use.\n  * Please use the `ifUserInGroup` directive instead\n  */\n  User.prototype.groupTest = function groupTest(expr) {\n    if(expr instanceof RegExp && this.matchesGroupExpression(expr)){\n      return true;\n    }else if(this.inGroup(expr)){\n      return true;\n    }else{\n      return false;\n    }\n  };\n\n  this.$get = [\n    '$q','$http','STORMPATH_CONFIG','$rootScope','$spFormEncoder','$spErrorTransformer', '$processSocialAuthToken',\n    function userServiceFactory($q,$http,STORMPATH_CONFIG,$rootScope,$spFormEncoder,$spErrorTransformer, $processSocialAuthToken){\n      function UserService(){\n        this.cachedUserOp = null;\n\n        /**\n          * @ngdoc property\n          *\n          * @name currentUser\n          *\n          * @propertyOf stormpath.userService.$user\n          *\n          * @description\n          *\n          * Retains the result of the last call to {@link stormpath.userService.$user#methods_get $user.get()}.\n          * This property is set after every resolution of the {@link stormpath.userService.$user#methods_get $user.get()} promise.\n          *\n          * If the user state is unknown (while {@link stormpath.userService.$user#methods_get $user.get()}\n          * is waiting to be resolved), this value is `null`.\n          *\n          * If the call to {@link stormpath.userService.$user#methods_get $user.get()} has resolved, one of the following will happen:\n          * * If the user is not logged in, this value will be `false`.\n          * * If the user is logged in, this value will be the account object of the user.\n          *\n          */\n\n        this.currentUser = null;\n        return this;\n      }\n      UserService.prototype.create = function(accountData){\n        /**\n         * @ngdoc function\n         *\n         * @name create\n         *\n         * @methodOf stormpath.userService.$user\n         *\n         * @param {Object} accountData\n         *\n         * An object literal for passing the data\n         * to the new account.\n         *\n         * Required fields:\n         * * `givenName` - the user's first name\n         * * `surname` - the user's last name\n         * * `email` - the email address of the user\n         * * `password` - the password that the user wishes to use for their\n         * account.  Must meet the password requirements that you have specified\n         * on the directory that this account will be created in.\n         *\n         * @returns {promise}\n         *\n         * A promise representing the operation to create a\n         * new user.  If an error occurs (duplicate email, weak password), the\n         * promise will be rejected and the http response will be passed.\n         * If the operation is successful, the promise\n         * will be resolved with a boolean `enabled` value.\n         *\n         * * If `true`, the account's status is Enabled and you can proceed with authenticating the user.\n         *\n         * * If `false`, the account's status is Unverified.\n         * This will be the case when you have enabled the email verification workflow on the directory of this\n         * account.\n         *\n         * @description\n         *\n         * Attempts to create a new user by submitting the given `accountData` as\n         * JSON to `/register`.  The POST endpoint can be modified via the\n         * {@link api/stormpath.STORMPATH_CONFIG:STORMPATH_CONFIG#properties_REGISTER_URI REGISTER_URI}\n         * config option.\n         *\n         * @example\n         *\n         * <pre>\n         * $user.create(accountData)\n         *   .then(function(account){\n         *     if(account.status === 'ENABLED'){\n         *       // The account is enabled and ready to use\n         *     }else if(account.status === 'UNVERIFIED'){\n         *       // The account requires email verification\n         *     }\n         *   })\n         *   .catch(function(err){\n         *     // Show the error message to the user\n         *     $scope.error = err.message;\n         *   });\n         * </pre>\n         */\n\n        return $http({\n          url: STORMPATH_CONFIG.getUrl('REGISTER_URI'),\n          method: 'POST',\n          data: accountData\n        })\n        .then(function(response){\n          var account = response.data.account || response.data;\n          registeredEvent(account);\n          return $q.resolve(account);\n        },function(httpResponse){\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        });\n\n      };\n      UserService.prototype.get = function get(bypassCache) {\n        /**\n         * @ngdoc function\n         *\n         * @name get\n         *\n         * @methodOf stormpath.userService.$user\n         *\n         * @param {Boolean} [bypassCache=false]\n         *\n         * By default, the UserService will cache the user object after it is\n         * retrieved the first time.  Specify `true` if you need to bypass this\n         * cache, e.g. after updating the user's custom data.\n         *\n         * @returns {promise}\n         *\n         * A promise representing the operation to get the current user data.\n         *\n         * @description\n         *\n         * Attempt to get the current user.  Returns a promise.  If the user\n         * is authenticated, the promise will be resolved with the user object.\n         * If the user is not authenticated, the promise will be rejected and\n         * passed the error response from the $http service.\n         *\n         * If you cannot make use of the promise, you can also observe the\n         * {@link $notLoggedin $notLoggedin} or {@link $currentUser $currentUser}\n         * events.  They are emitted when this method has a success or failure.\n         *\n         * The result of this operation will be cached on the {@link stormpath.userService.$user#properties_currentuser $user.currentUser}\n         * property.\n         *\n         * The user object is a Stormpath Account object, which is wrapped by a\n         * {@link eh User} type.  It is fetched from the `/me` endpoint on your\n         * server, which is provided by our framework integrations.\n         *\n         * @example\n         *\n         * <pre>\n         * var myApp = angular.module('myApp', ['stormpath']);\n         *\n         * myApp.controller('MyAppCtrl', function ($scope, $user) {\n         *   $user.get()\n         *     .then(function (user) {\n         *       console.log('The current user is', user);\n         *     })\n         *     .catch(function (error) {\n         *       console.log('Error getting user', error);\n         *     });\n         * });\n         * </pre>\n         *\n         */\n        var op = $q.defer();\n        var self = this;\n\n        if (self.cachedUserOp) {\n          return self.cachedUserOp.promise;\n        }\n\n        if (self.currentUser !== null && self.currentUser!==false && bypassCache!==true) {\n          op.resolve(self.currentUser);\n          return op.promise;\n        }\n\n        self.cachedUserOp = op;\n        var beforeLoad = self.currentUser ? $q.resolve() : $processSocialAuthToken();\n\n        return beforeLoad.then(function() {\n          $http.get(STORMPATH_CONFIG.getUrl('CURRENT_USER_URI')).then(function(response) {\n            self.cachedUserOp = null;\n            self.currentUser = new User(response.data.account || response.data);\n            currentUserEvent(self.currentUser);\n            op.resolve(self.currentUser);\n          }, function(response) {\n            self.currentUser = false;\n            if (response.status===401) {\n              notLoggedInEvent();\n            }\n            self.cachedUserOp = null;\n            op.reject(response);\n          });\n          return op.promise;\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name resendVerificationEmail\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to resend a verification token\n       * to the given email address.  Will resolve, even if the email address\n       * does not exist.  If rejected there was a network error.\n       *\n       * @description\n       *\n       * Re-sends the verification email to the account specified by the\n       * username or email address.\n       *\n       * @param  {Object} data\n       *\n       * An object literal for passing the username or email.\n       * ```\n       * {\n       *   username: 'email address or username'\n       * }\n       * ```\n       */\n      UserService.prototype.resendVerificationEmail = function resendVerificationEmail(data){\n        return $http({\n          method: 'POST',\n          url: STORMPATH_CONFIG.getUrl('EMAIL_VERIFICATION_ENDPOINT'),\n          data: data\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name verify\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to verify the given\n       * email verification token token.  If resolved the account has been\n       * verified and can be used for login.  If rejected the token is expired\n       * or has already been used.\n       *\n       * @param  {String} sptoken\n       *\n       * The value of the `sptoken` that was sent by email to the user\n       *\n       * @description\n       *\n       * Verifies a new account, using the `sptoken` that was sent to the user\n       * by email.\n       */\n      UserService.prototype.verify = function verify(token){\n        return $http({\n          url: STORMPATH_CONFIG.getUrl('EMAIL_VERIFICATION_ENDPOINT') + '?sptoken='+token\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name verifyPasswordResetToken\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * A $http promise representing the operation to verify the given password\n       * reset token token.  If resolved, the token can be used.  If rejected\n       * the token cannot be used.\n       *\n       * @description\n       *\n       * Verifies a password reset token that was sent to the user by email.\n       * If valid, the token can be used to reset the user's password.  If not\n       * valid it means that the token has expired or has already been used.\n       *\n       * Use this method to verify the token, before asking the user to specify\n       * a new password.  If the token is invalid the user must ask for another.\n       *\n       * @param  {String} sptoken\n       *\n       * The `sptoken` that was delivered to the user by email\n       */\n      UserService.prototype.verifyPasswordResetToken = function verifyPasswordResetToken(token){\n        return $http({\n          url: STORMPATH_CONFIG.getUrl('CHANGE_PASSWORD_ENDPOINT')+'?sptoken='+token\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name passwordResetRequest\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to generate a password\n       * reset token for the given email address.  Will resolve, even if the\n       * email address does not exist.  If rejected there was a network error.\n       *\n       * @description\n       *\n       * Triggers a password reset email to the given username or email address.\n       *\n       * @param  {Object} data\n       *\n       * An object literal for passing the email address.\n       * ```\n       * {\n       *   email: 'email address of the user'\n       * }\n       * ```\n       */\n      UserService.prototype.passwordResetRequest = function passwordResetRequest(data){\n        return $http({\n          method: 'POST',\n          url: STORMPATH_CONFIG.getUrl('FORGOT_PASSWORD_ENDPOINT'),\n          data: data\n        })\n        .catch(function(httpResponse){\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        });\n      };\n\n      /**\n       * @ngdoc function\n       *\n       * @name resetPassword\n       *\n       * @methodOf stormpath.userService.$user\n       *\n       * @returns {promise}\n       *\n       * An $http promise representing the operation to reset the password and\n       * consume the token.  If resolved the password was successfully changed,\n       * if rejected the token is invalid or the posted password does not meet\n       * the password strength rules of the directory.\n       *\n       * @description\n       *\n       * Resets a user's password, using a token that was emailed to the user.\n       *\n       * @param {String} token\n       *\n       * The `sptoken` that was sent to the user via email.\n       *\n       * @param  {Object} data\n       *\n       * An object literal for passing the new password.  Must follow this\n       * format:\n       * ```\n       * {\n       *   password: 'the new password'\n       * }\n       * ```\n       */\n      UserService.prototype.resetPassword = function resetPassword(token,data){\n        data.sptoken = token;\n        return $http({\n          method: 'POST',\n          url:STORMPATH_CONFIG.getUrl('CHANGE_PASSWORD_ENDPOINT'),\n          data: data\n        })\n        .catch(function(httpResponse){\n          return $q.reject($spErrorTransformer.transformError(httpResponse));\n        });\n      };\n      function registeredEvent(account){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.userService.$user#$registered\n         *\n         * @eventOf stormpath.userService.$user\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {account} account\n         *\n         * The object of the account that was created.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.userService.$user#methods_create $user.create()}\n         * is successful.  The account object is returned, and you can inspec\n         * the account's status to know if email verification is required.\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.REGISTERED_EVENT_NAME,account);\n      }\n      function currentUserEvent(user){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.userService.$user#$currentUser\n         *\n         * @eventOf stormpath.userService.$user\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @param {User} user\n         *\n         * The current user object.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.userService.$user#methods_get $user.get()}\n         * and provides the user object as the second parameter.\n         *\n         * See the next section, the $notLoggeInEvent, for example usage.\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.GET_USER_EVENT,user);\n      }\n      function notLoggedInEvent(){\n        /**\n         * @ngdoc event\n         *\n         * @name stormpath.userService.$user#$notLoggedIn\n         *\n         * @eventOf stormpath.userService.$user\n         *\n         * @eventType broadcast on root scope\n         *\n         * @param {Object} event\n         *\n         * Angular event object.\n         *\n         * @description\n         *\n         * This event is broadcast when a call to\n         * {@link stormpath.userService.$user#methods_get $user.get()}\n         * results in an authentication failure.\n         *\n         * This event is useful for situations where you want to trigger\n         * the call to get the current user, but need to respond to it\n         * from some other place in your application.  An example could be,\n         * during application bootstrap, you make a single call to get the current\n         * user from the run function, then react to it inside your\n         * application controller.\n         *\n         * @example\n         *\n         * <pre>\n         * var myApp = angular.module('myApp', ['stormpath']);\n         * myApp.run(function($user){\n         *   //\n         *   // Once our app is ready to run, trigger a call to $user.get()\n         *   // We can then do other things while we wait for the result\n         *   //\n         *   $user.get();\n         * });\n         *\n         * myApp.controller('MyAppCtrl', function ($scope, $rootScope) {\n         *   $scope.isVisible = false; // Wait for authentication\n         *   $rootScope.$on('$notLoggedIn',function(){\n         *      $state.$go('login');\n         *   });\n         *   $rootScope.$on('$currentUser',function(e,user){\n         *      $scope.isVisible = true;\n         *   });\n         *\n         * });\n         * </pre>\n         */\n        $rootScope.$broadcast(STORMPATH_CONFIG.NOT_LOGGED_IN_EVENT);\n      }\n\n      var userService = new UserService();\n      $rootScope.$on(STORMPATH_CONFIG.SESSION_END_EVENT,function(){\n        userService.currentUser = false;\n      });\n      return userService;\n    }\n  ];\n}]);\n"
  },
  {
    "path": "src/stormpath.utils.js",
    "content": "'use strict';\n\n/**\n * This module and factory are intentionally excluded from NG Docs.\n *\n * The factory is an internal utility used to check whether an URL is on the\n * same domain on which the SPA is hosted.\n */\n\nangular.module('stormpath.utils', ['stormpath.CONFIG'])\n.factory('$isCurrentDomain', ['$window', function($window) {\n  return function(url) {\n    var link = $window.document.createElement('a');\n    link.href = url;\n\n    return (link.host === \"\") || $window.location.host === link.host.replace(/:443$/, \"\");\n  };\n}])\n.constant('$spHeaders', {\n  // The placeholders in the value are replaced by the `grunt dist` command.\n  'X-Stormpath-Agent': '@@PACKAGE_NAME/@@PACKAGE_VERSION' + ' angularjs/' + angular.version.full\n})\n.provider('$spErrorTransformer', [function $spErrorTransformer(){\n  /**\n   * This service is intentionally excluded from NG Docs.\n   *\n   * It is an internal utility for producing error objects from $http response\n   * errors.\n   */\n\n  this.$get = [\n    function formEncoderServiceFactory(){\n\n      function ErrorTransformerService(){\n\n      }\n\n      ErrorTransformerService.prototype.transformError = function transformError(httpResponse){\n        var errorMessage = null;\n\n        if (httpResponse.data) {\n          errorMessage = httpResponse.data.message || httpResponse.data.error;\n        }\n\n        if (!errorMessage) {\n          errorMessage = 'An error occured when communicating with the server.';\n        }\n\n        var error = new Error(errorMessage);\n\n        error.httpResponse = httpResponse;\n        error.statusCode = httpResponse.status;\n        return error;\n      };\n\n      return new ErrorTransformerService();\n    }\n  ];\n}])\n.provider('$spFormEncoder', [function $spFormEncoder(){\n  /**\n   * This service is intentionally excluded from NG Docs.\n   * It is an internal utility.\n   */\n\n  this.$get = [\n    function formEncoderServiceFactory(){\n\n      function FormEncoderService(){\n        var encoder = new UrlEncodedFormParser();\n        this.encodeUrlForm = encoder.encode.bind(encoder);\n        return this;\n      }\n\n      FormEncoderService.prototype.formPost = function formPost(httpRequest){\n        var h = httpRequest.headers ? httpRequest.headers : (httpRequest.headers = {});\n        h['Content-Type'] = 'application/x-www-form-urlencoded';\n        httpRequest.data = this.encodeUrlForm(httpRequest.data);\n        return httpRequest;\n      };\n\n      function UrlEncodedFormParser(){\n\n        // Copy & modify from https://github.com/hapijs/qs/blob/master/lib/stringify.js\n\n        this.delimiter = '&';\n        this.arrayPrefixGenerators = {\n          brackets: function (prefix) {\n            return prefix + '[]';\n          },\n          indices: function (prefix, key) {\n            return prefix + '[' + key + ']';\n          },\n          repeat: function (prefix) {\n            return prefix;\n          }\n        };\n        return this;\n      }\n      UrlEncodedFormParser.prototype.stringify = function stringify(obj, prefix, generateArrayPrefix) {\n\n        if (obj instanceof Date) {\n          obj = obj.toISOString();\n        }\n        else if (obj === null) {\n          obj = '';\n        }\n\n        if (typeof obj === 'string' ||\n          typeof obj === 'number' ||\n          typeof obj === 'boolean') {\n\n          return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)];\n        }\n\n        var values = [];\n\n        if (typeof obj === 'undefined') {\n          return values;\n        }\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          if (Array.isArray(obj)) {\n            values = values.concat(this.stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix));\n          }\n          else {\n            values = values.concat(this.stringify(obj[key], prefix + '[' + key + ']', generateArrayPrefix));\n          }\n        }\n\n        return values;\n      };\n      UrlEncodedFormParser.prototype.encode = function encode(obj, options) {\n\n        options = options || {};\n        var delimiter = typeof options.delimiter === 'undefined' ? this.delimiter : options.delimiter;\n\n        var keys = [];\n\n        if (typeof obj !== 'object' ||\n          obj === null) {\n\n          return '';\n        }\n\n        var arrayFormat;\n        if (options.arrayFormat in this.arrayPrefixGenerators) {\n          arrayFormat = options.arrayFormat;\n        }\n        else if ('indices' in options) {\n          arrayFormat = options.indices ? 'indices' : 'repeat';\n        }\n        else {\n          arrayFormat = 'indices';\n        }\n\n        var generateArrayPrefix = this.arrayPrefixGenerators[arrayFormat];\n\n        var objKeys = Object.keys(obj);\n        for (var i = 0, il = objKeys.length; i < il; ++i) {\n          var key = objKeys[i];\n          keys = keys.concat(this.stringify(obj[key], key, generateArrayPrefix));\n        }\n\n        return keys.join(delimiter);\n      };\n\n      return new FormEncoderService();\n    }\n  ];\n}])\n/**\n* Intentionally excluded from the NG Docs.\n*\n* Shallow-transforms snake-cased keys in an object into camelCased keys\n*/\n.factory('$normalizeObjectKeys', function() {\n  return function normalizeObjectKeys(obj) {\n    var camelCasedObj = {};\n\n    Object.keys(obj).forEach(function(key) {\n      if (obj.hasOwnProperty(key)) {\n        var camelCasedKey = key.replace(/_([A-Za-z])/g, function(all, char) {\n          return char.toUpperCase();\n        });\n\n        camelCasedObj[camelCasedKey] = obj[key];\n      }\n    });\n\n    return camelCasedObj;\n  };\n})\n\n.factory('$encodeQueryParams', function() {\n  return function encodeQueryParams(obj) {\n    if (!angular.isObject(obj)) {\n      return '';\n    }\n\n    var query = Object.keys(obj).map(function(key) {\n      return encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]);\n    }).join('&');\n\n    return query ? ('?' + query) : query;\n  };\n})\n\n.factory('$decodeQueryParams', function() {\n  return function decodeQueryParams(str) {\n    if (!angular.isString(str) || str.length === 0) {\n      return {};\n    }\n\n    var params = {};\n\n    str.substr(1).split('&').forEach(function(pair) {\n      var parts = pair.split('=');\n      params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);\n    });\n\n    return params;\n  };\n})\n\n.factory('$parseUrl', ['$decodeQueryParams', function($decodeQueryParams) {\n  return function parseUrl(url) {\n    var parser = document.createElement('a');\n    parser.href = url;\n\n    return {\n      protocol: parser.protocol,\n      hash: parser.hash,\n      host: parser.hostname,\n      port: parser.port,\n      pathname: parser.pathname,\n      query: parser.search,\n      search: $decodeQueryParams(parser.search)\n    };\n  };\n}])\n\n.factory('$getLocalUrl', ['$location', '$parseUrl', function($location, $parseUrl) {\n\n  return function(uri) {\n    if (uri && uri.charAt(0) !== '/') {\n      var parsedUri = $parseUrl(uri);\n      uri = parsedUri.pathname + parsedUri.query + parsedUri.hash;\n    }\n\n    return $location.protocol()\n      + '://'\n      + $location.host()\n      + ($location.port() ? (':' + $location.port()) : '')\n      + uri;\n\n  };\n}]);\n"
  },
  {
    "path": "src/stormpath.view-model.js",
    "content": "(function () {\n  'use strict';\n\n  function ViewModelService($http, STORMPATH_CONFIG) {\n    this.$http = $http;\n    this.STORMPATH_CONFIG = STORMPATH_CONFIG;\n  }\n\n  ViewModelService.prototype.getLoginModel = function getLoginModel() {\n    return this.$http.get(this.STORMPATH_CONFIG.getUrl('AUTHENTICATION_ENDPOINT'), {\n      headers: {\n        'Accept': 'application/json'\n      }\n    }).then(function (response) {\n      return response.data;\n    });\n  };\n\n  ViewModelService.prototype.getRegisterModel = function getRegisterModel() {\n    return this.$http.get(this.STORMPATH_CONFIG.getUrl('REGISTER_URI'), {\n      headers: {\n        'Accept': 'application/json'\n      }\n    }).then(function (response) {\n      return response.data;\n    });\n  };\n\n  angular.module('stormpath.viewModelService', ['stormpath.utils'])\n  .provider('$viewModel', function () {\n    this.$get = ['$http', 'STORMPATH_CONFIG', function viewModelFactory($http, STORMPATH_CONFIG) {\n      return new ViewModelService($http, STORMPATH_CONFIG);\n    }];\n  });\n}());\n"
  },
  {
    "path": "test/.jshintrc",
    "content": "{\n  \"globals\": {\n    \"describe\": false,\n    \"by\": false\n    \"it\": false\n  }\n}\n"
  },
  {
    "path": "test/protractor/login.js",
    "content": "/*\n  Very simple test!  It assumes you're running an app\n  which is built like our sample app in the guide, and not using\n  an alternate defaultPostLoginState.\n */\ndescribe('Demo Login Form', function() {\n  it('should exist on the /login route page', function() {\n    browser.get('http://localhost:9000/login');\n    expect(element(by.css('[sp-login-form]')).isPresent()).toBe(true);\n  });\n\n  it('should send me to the homepage when i login', function() {\n    browser.get('http://localhost:9000/login');\n\n    element(by.id('spUsername')).sendKeys('robert@stormpath.com');\n    element(by.id('spPassword')).sendKeys('robert@stormpath.comA1');\n    element(by.css('form')).submit();\n    expect(browser.getCurrentUrl()).toBe('http://localhost:9000/');\n  });\n\n  it('should redirect me to the homepage if i go back to the login page', function() {\n    browser.navigate().back();\n    expect(browser.getCurrentUrl()).toBe('http://localhost:9000/');\n  });\n\n  /*\n    This test is broken since 0.5.5, because I removed something that would\n    wait for the auth state.  I need to bring that functionality back,\n    or just suggest the use of 'waitForUser' sp config option.\n   */\n\n  // it('should redirect me to the homepage if navigate to /login while logged in', function() {\n  //   browser.get('http://localhost:9000/login');\n  //   expect(browser.getCurrentUrl()).toBe('http://localhost:9000/');\n  // });\n});"
  }
]