├── examples ├── angularjs │ ├── public │ │ ├── css │ │ │ ├── .gitkeep │ │ │ └── app.css │ │ ├── img │ │ │ └── .gitkeep │ │ ├── partials │ │ │ ├── .gitkeep │ │ │ ├── partial1.html │ │ │ ├── login.html │ │ │ └── signup.html │ │ ├── js │ │ │ ├── services.js │ │ │ ├── directives.js │ │ │ ├── filters.js │ │ │ ├── controllers.js │ │ │ └── app.js │ │ ├── index.html │ │ └── lib │ │ │ └── angular │ │ │ ├── angular-route.min.js │ │ │ └── angular.min.js │ ├── package.json │ ├── README.md │ └── app.js ├── http-basic-auth │ ├── public │ │ ├── css │ │ │ ├── .gitkeep │ │ │ └── app.css │ │ ├── img │ │ │ └── .gitkeep │ │ ├── partials │ │ │ ├── .gitkeep │ │ │ ├── partial1.html │ │ │ ├── login.html │ │ │ └── signup.html │ │ ├── js │ │ │ ├── directives.js │ │ │ ├── filters.js │ │ │ ├── controllers.js │ │ │ ├── app.js │ │ │ └── services.js │ │ ├── index.html │ │ └── lib │ │ │ └── angular │ │ │ └── angular-route.min.js │ ├── package.json │ ├── README.md │ └── app.js ├── login │ ├── views │ │ ├── index.ejs │ │ ├── account.ejs │ │ ├── login.ejs │ │ └── layout.ejs │ ├── package.json │ ├── README.md │ └── app.js ├── signup-login │ ├── views │ │ ├── index.ejs │ │ ├── account.ejs │ │ ├── login.ejs │ │ ├── layout.ejs │ │ └── signup.ejs │ ├── package.json │ ├── README.md │ └── app.js └── stateless-login │ ├── views │ ├── index.ejs │ ├── account.ejs │ ├── login.ejs │ └── layout.ejs │ ├── package.json │ ├── README.md │ └── app.js ├── lib └── passport-userapp │ ├── index.js │ └── strategy.js ├── package.json ├── LICENSE └── README.md /examples/angularjs/public/css/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/angularjs/public/img/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/angularjs/public/partials/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/css/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/img/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/partials/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/login/views/index.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (!user) { %> 3 |

Welcome! Please log in.

4 | <% } else { %> 5 |

Hello, <%= user.username %>.

6 | <% } %> 7 | -------------------------------------------------------------------------------- /examples/signup-login/views/index.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (!user) { %> 3 |

Welcome! Please log in.

4 | <% } else { %> 5 |

Hello, <%= user.username %>.

6 | <% } %> 7 | -------------------------------------------------------------------------------- /examples/stateless-login/views/index.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (!user) { %> 3 |

Welcome! Please log in.

4 | <% } else { %> 5 |

Hello, <%= user.username %>.

6 | <% } %> 7 | -------------------------------------------------------------------------------- /examples/angularjs/public/partials/partial1.html: -------------------------------------------------------------------------------- 1 |

Here's all the articles from the back-end API using our session token:

2 | 3 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/partials/partial1.html: -------------------------------------------------------------------------------- 1 |

Here's all the articles from the back-end API using our session token:

2 | 3 | -------------------------------------------------------------------------------- /examples/angularjs/public/js/services.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Services */ 4 | 5 | 6 | // Demonstrate how to register services 7 | // In this case it is a simple value service. 8 | angular.module('myApp.services', []). 9 | value('version', '0.1'); 10 | -------------------------------------------------------------------------------- /lib/passport-userapp/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | var Strategy = require('./strategy'); 5 | 6 | /** 7 | * Framework version. 8 | */ 9 | exports.version = '0.1.0'; 10 | 11 | /** 12 | * Expose constructors. 13 | */ 14 | exports.Strategy = Strategy; 15 | -------------------------------------------------------------------------------- /examples/angularjs/public/js/directives.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Directives */ 4 | 5 | 6 | angular.module('myApp.directives', []). 7 | directive('appVersion', ['version', function(version) { 8 | return function(scope, elm, attrs) { 9 | elm.text(version); 10 | }; 11 | }]); 12 | -------------------------------------------------------------------------------- /examples/angularjs/public/js/filters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Filters */ 4 | 5 | angular.module('myApp.filters', []). 6 | filter('interpolate', ['version', function(version) { 7 | return function(text) { 8 | return String(text).replace(/\%VERSION\%/mg, version); 9 | } 10 | }]); 11 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/js/directives.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Directives */ 4 | 5 | 6 | angular.module('myApp.directives', []). 7 | directive('appVersion', ['version', function(version) { 8 | return function(scope, elm, attrs) { 9 | elm.text(version); 10 | }; 11 | }]); 12 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/js/filters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Filters */ 4 | 5 | angular.module('myApp.filters', []). 6 | filter('interpolate', ['version', function(version) { 7 | return function(text) { 8 | return String(text).replace(/\%VERSION\%/mg, version); 9 | } 10 | }]); 11 | -------------------------------------------------------------------------------- /examples/login/views/account.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 |

Username: <%= user.username %>

3 |

Email: <%= user.email %>

4 | 5 | <% if(user.groups) { %> 6 |
7 |

Groups:

8 | 13 |
14 | <% } %> 15 | -------------------------------------------------------------------------------- /examples/signup-login/views/account.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 |

Username: <%= user.username %>

3 |

Email: <%= user.email %>

4 | 5 | <% if(user.groups) { %> 6 |
7 |

Groups:

8 | 13 |
14 | <% } %> 15 | -------------------------------------------------------------------------------- /examples/stateless-login/views/account.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 |

Username: <%= user.username %>

3 |

Email: <%= user.email %>

4 | 5 | <% if(user.groups) { %> 6 |
7 |

Groups:

8 | 13 |
14 | <% } %> 15 | -------------------------------------------------------------------------------- /examples/login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"passport-userapp-examples-login", 3 | "version":"0.0.0", 4 | "dependencies":{ 5 | "express":"3.x.x", 6 | "connect-flash":"0.1.x", 7 | "ejs":">= 0.0.0", 8 | "ejs-locals":">= 0.0.0", 9 | "passport":">= 0.0.0", 10 | "passport-userapp":">= 0.0.0", 11 | "underscore":"1.4.3" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/angularjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"passport-userapp-examples-login", 3 | "version":"0.0.0", 4 | "dependencies":{ 5 | "express":"3.x.x", 6 | "connect-flash":"0.1.x", 7 | "ejs":">= 0.0.0", 8 | "ejs-locals":">= 0.0.0", 9 | "passport":">= 0.0.0", 10 | "passport-userapp":">= 0.2.0", 11 | "underscore":"1.4.3" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/http-basic-auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"passport-userapp-examples-login", 3 | "version":"0.0.0", 4 | "dependencies":{ 5 | "express":"3.x.x", 6 | "connect-flash":"0.1.x", 7 | "ejs":">= 0.0.0", 8 | "ejs-locals":">= 0.0.0", 9 | "passport":">= 0.0.0", 10 | "passport-userapp":">= 0.2.0", 11 | "underscore":"1.4.3" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/stateless-login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"passport-userapp-examples-login", 3 | "version":"0.0.0", 4 | "dependencies":{ 5 | "express":"3.x.x", 6 | "connect-flash":"0.1.x", 7 | "ejs":">= 0.0.0", 8 | "ejs-locals":">= 0.0.0", 9 | "passport":">= 0.0.0", 10 | "passport-userapp":">= 1.0.0", 11 | "underscore":"1.4.3" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/angularjs/public/partials/login.html: -------------------------------------------------------------------------------- 1 |

Please log in

2 | 3 |
4 |
5 |
6 |

or Log in with Google

7 |

8 |
9 | 10 |

Sign up

-------------------------------------------------------------------------------- /examples/signup-login/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passport-userapp-examples-login", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "express": "3.x.x", 6 | "connect-flash": "0.1.x", 7 | "ejs": ">= 0.0.0", 8 | "ejs-locals": ">= 0.0.0", 9 | "passport": ">= 0.0.0", 10 | "passport-userapp": "userapp-io/passport-userapp", 11 | "underscore": "1.4.3", 12 | "userapp": "~0.2.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/partials/login.html: -------------------------------------------------------------------------------- 1 |

Please log in

2 | 3 |
4 |
5 |
6 |

or Log in with Google

7 |

8 |
9 | 10 |

Sign up

-------------------------------------------------------------------------------- /examples/login/views/login.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (message) { %> 3 |

<%= message %>

4 | <% } %> 5 |
6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /examples/signup-login/views/login.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (message) { %> 3 |

<%= message %>

4 | <% } %> 5 |
6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /examples/stateless-login/views/login.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (message) { %> 3 |

<%= message %>

4 | <% } %> 5 |
6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /examples/login/views/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Passport-UserApp Example 5 | 6 | 7 | <% if (!user) { %> 8 |

9 | Home | 10 | Log In 11 |

12 | <% } else { %> 13 |

14 | Home | 15 | Account | 16 | Log Out 17 |

18 | <% } %> 19 | <%- body %> 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/stateless-login/views/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Passport-UserApp Example 5 | 6 | 7 | <% if (!user) { %> 8 |

9 | Home | 10 | Log In 11 |

12 | <% } else { %> 13 |

14 | Home | 15 | Account | 16 | Log Out 17 |

18 | <% } %> 19 | <%- body %> 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/angularjs/public/partials/signup.html: -------------------------------------------------------------------------------- 1 |

Sign up

2 | 3 |
4 |
5 |
6 |
7 |

or Sign up with Google

8 |

9 |
10 | 11 |

Log in

-------------------------------------------------------------------------------- /examples/http-basic-auth/public/partials/signup.html: -------------------------------------------------------------------------------- 1 |

Sign up

2 | 3 |
4 |
5 |
6 |
7 |

or Sign up with Google

8 |

9 |
10 | 11 |

Log in

-------------------------------------------------------------------------------- /examples/signup-login/views/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Passport-UserApp Example 5 | 6 | 7 | <% if (!user) { %> 8 |

9 | Home | 10 | Log In | 11 | Sign Up 12 |

13 | <% } else { %> 14 |

15 | Home | 16 | Account | 17 | Log Out 18 |

19 | <% } %> 20 | <%- body %> 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/angularjs/public/css/app.css: -------------------------------------------------------------------------------- 1 | /* app css stylesheet */ 2 | 3 | .menu { 4 | list-style: none; 5 | border-bottom: 0.1em solid black; 6 | margin-bottom: 2em; 7 | padding: 0 0 0.5em; 8 | } 9 | 10 | .menu:before { 11 | content: "["; 12 | } 13 | 14 | .menu:after { 15 | content: "]"; 16 | } 17 | 18 | .menu > li { 19 | display: inline; 20 | } 21 | 22 | .menu > li:before { 23 | content: "|"; 24 | padding-right: 0.3em; 25 | } 26 | 27 | .menu > li:nth-child(1):before { 28 | content: ""; 29 | padding: 0; 30 | } 31 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/css/app.css: -------------------------------------------------------------------------------- 1 | /* app css stylesheet */ 2 | 3 | .menu { 4 | list-style: none; 5 | border-bottom: 0.1em solid black; 6 | margin-bottom: 2em; 7 | padding: 0 0 0.5em; 8 | } 9 | 10 | .menu:before { 11 | content: "["; 12 | } 13 | 14 | .menu:after { 15 | content: "]"; 16 | } 17 | 18 | .menu > li { 19 | display: inline; 20 | } 21 | 22 | .menu > li:before { 23 | content: "|"; 24 | padding-right: 0.3em; 25 | } 26 | 27 | .menu > li:nth-child(1):before { 28 | content: ""; 29 | padding: 0; 30 | } 31 | -------------------------------------------------------------------------------- /examples/angularjs/public/js/controllers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Controllers */ 4 | 5 | angular.module('myApp.controllers', []) 6 | .controller('MyCtrl1', function($scope, $http) { 7 | // Call the back-end API which will be authenticated using our session 8 | $http({method: 'GET', url: '/articles'}). 9 | success(function(data, status, headers, config) { 10 | //The API call to the back-end was successful (i.e. a valid session) 11 | $scope.articles = data; 12 | }). 13 | error(function(data, status, headers, config) { 14 | alert("The API call to the back-end was NOT successful (i.e. an invalid session)."); 15 | }); 16 | }); -------------------------------------------------------------------------------- /examples/signup-login/views/signup.ejs: -------------------------------------------------------------------------------- 1 | <% layout('layout') -%> 2 | <% if (message) { %> 3 |

<%= message %>

4 | <% } %> 5 |
6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 21 |
22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/js/controllers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Controllers */ 4 | 5 | angular.module('myApp.controllers', []) 6 | .controller('MyCtrl1', function($scope, $http, Base64, user) { 7 | // Call the back-end API which will be authenticated using our token 8 | $http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode(':' + user.token()); 9 | $http({method: 'GET', url: '/articles'}). 10 | success(function(data, status, headers, config) { 11 | //The API call to the back-end was successful (i.e. a valid token) 12 | $scope.articles = data; 13 | }). 14 | error(function(data, status, headers, config) { 15 | alert("The API call to the back-end was NOT successful (i.e. an invalid token)."); 16 | }); 17 | }); -------------------------------------------------------------------------------- /examples/angularjs/public/js/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | // Declare app level module which depends on filters, and services 5 | angular.module('myApp', [ 6 | 'ngRoute', 7 | 'myApp.filters', 8 | 'myApp.services', 9 | 'myApp.directives', 10 | 'myApp.controllers', 11 | 'UserApp' 12 | ]). 13 | config(['$routeProvider', function($routeProvider) { 14 | $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true}); 15 | $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true}); 16 | $routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'}); 17 | $routeProvider.otherwise({redirectTo: '/view1'}); 18 | }]) 19 | .run(function($rootScope, user) { 20 | user.init({ appId: 'YOUR-USERAPP-APP-ID' }); // Your UserApp App Id: https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id- 21 | }); 22 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/js/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | // Declare app level module which depends on filters, and services 5 | angular.module('myApp', [ 6 | 'ngRoute', 7 | 'myApp.filters', 8 | 'myApp.services', 9 | 'myApp.directives', 10 | 'myApp.controllers', 11 | 'UserApp' 12 | ]). 13 | config(['$routeProvider', function($routeProvider) { 14 | $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true}); 15 | $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true}); 16 | $routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'}); 17 | $routeProvider.otherwise({redirectTo: '/view1'}); 18 | }]) 19 | .run(function($rootScope, user) { 20 | user.init({ appId: 'YOUR-USERAPP-APP-ID' }); // Your UserApp App Id: https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id- 21 | }); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passport-userapp", 3 | "version": "1.1.2", 4 | "description": "Password and token authentication strategy using UserApp for Passport", 5 | "homepage": "https://github.com/userapp-io/passport-userapp", 6 | "author": { 7 | "name": "Timothy E. Johansson", 8 | "email": "timothy.johansson@userapp.io" 9 | }, 10 | "company": { 11 | "name": "UserApp", 12 | "product": "UserApp", 13 | "homepage": "https://www.userapp.io/" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/userapp-io/passport-userapp.git" 18 | }, 19 | "main": "./lib/passport-userapp", 20 | "dependencies": { 21 | "passport": ">= 0.1.1", 22 | "userapp": ">= 0.2.3" 23 | }, 24 | "engines": { 25 | "node": ">= 0.4.0" 26 | }, 27 | "licenses": [ 28 | { 29 | "type": "MIT", 30 | "url": "http://www.opensource.org/licenses/MIT" 31 | } 32 | ], 33 | "keywords": [ 34 | "passport", 35 | "userapp", 36 | "user", 37 | "user management", 38 | "auth", 39 | "authentication", 40 | "identity" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 UserApp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/angularjs/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My AngularJS App 6 | 7 | 8 | 9 | 13 | 14 |
15 | 16 |
Angular seed app: v
17 |
Email: {{ user.email }}
18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | My AngularJS App 6 | 7 | 8 | 9 | 13 | 14 |
15 | 16 |
Angular seed app: v
17 |
Email: {{ user.email }}
18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /examples/signup-login/README.md: -------------------------------------------------------------------------------- 1 | # Passport-UserApp - Example with signup and login 2 | 3 | 4 | 5 | Example of how to use the UserApp Passport strategy for authenticating using an HTML form with username and password, 6 | as well as signing up a new user. 7 | 8 | ## Getting Started 9 | 10 | * Get your UserApp [App Id](https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id-) and replace 'YOUR-USERAPP-APP-ID' in `app.js` with that id. 11 | 12 | * Install all the dependencies: 13 | 14 | `$ npm install` 15 | 16 | * Start the Node.js server 17 | 18 | `$ node app.js` 19 | 20 | * Browse to `http://localhost:3000` 21 | 22 | * Try to sign up and log in. 23 | 24 | ## Help 25 | 26 | Contact us via email at support@userapp.io or visit our [support center](https://help.userapp.io). 27 | 28 | ## License 29 | 30 | (The MIT License) 31 | 32 | Copyright (c) 2014 UserApp 33 | 34 | Permission is hereby granted, free of charge, to any person obtaining a copy of 35 | this software and associated documentation files (the "Software"), to deal in 36 | the Software without restriction, including without limitation the rights to 37 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 38 | the Software, and to permit persons to whom the Software is furnished to do so, 39 | subject to the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be included in all 42 | copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 46 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 47 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 48 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 49 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 50 | -------------------------------------------------------------------------------- /examples/login/README.md: -------------------------------------------------------------------------------- 1 | # Passport-UserApp - Example with login 2 | 3 | 4 | 5 | Example of how to use the UserApp Passport strategy for authenticating using an HTML form with username and password. 6 | 7 | ## Getting Started 8 | 9 | * Get your UserApp [App Id](https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id-) and replace 'YOUR-USERAPP-APP-ID' in `app.js` with that id. 10 | 11 | * Install all the dependencies: 12 | 13 | `$ npm install` 14 | 15 | * Start the Node.js server 16 | 17 | `$ node app.js` 18 | 19 | * Browse to `http://localhost:3000` 20 | 21 | * Go to the [UserApp Dashboard](https://app.userapp.io) and create a new user. 22 | 23 | * Try to log in with the new user. 24 | 25 | ## Help 26 | 27 | Contact us via email at support@userapp.io or visit our [support center](https://help.userapp.io). 28 | 29 | ## License 30 | 31 | (The MIT License) 32 | 33 | Copyright (c) 2014 UserApp 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy of 36 | this software and associated documentation files (the "Software"), to deal in 37 | the Software without restriction, including without limitation the rights to 38 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 39 | the Software, and to permit persons to whom the Software is furnished to do so, 40 | subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in all 43 | copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 47 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 48 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 49 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 50 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 51 | -------------------------------------------------------------------------------- /examples/stateless-login/README.md: -------------------------------------------------------------------------------- 1 | # Passport-UserApp - Example with stateless server session 2 | 3 | 4 | 5 | Example of how to use the UserApp Passport strategy for authenticating using an HTML form with username and password. 6 | This example will save the session token in a cookie named `ua_session_token` so the server can be restarted without 7 | logging out users. 8 | 9 | ## Getting Started 10 | 11 | * Get your UserApp [App Id](https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id-) and replace 'YOUR-USERAPP-APP-ID' in `app.js` with that id. 12 | 13 | * Install all the dependencies: 14 | 15 | `$ npm install` 16 | 17 | * Start the Node.js server 18 | 19 | `$ node app.js` 20 | 21 | * Browse to `http://localhost:3000` 22 | 23 | * Go to the [UserApp Dashboard](https://app.userapp.io) and create a new user. 24 | 25 | * Try to log in with the new user. 26 | 27 | * Also try to restart the server and check that you are still logged in. 28 | 29 | ## Help 30 | 31 | Contact us via email at support@userapp.io or visit our [support center](https://help.userapp.io). 32 | 33 | ## License 34 | 35 | (The MIT License) 36 | 37 | Copyright (c) 2014 UserApp 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy of 40 | this software and associated documentation files (the "Software"), to deal in 41 | the Software without restriction, including without limitation the rights to 42 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 43 | the Software, and to permit persons to whom the Software is furnished to do so, 44 | subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 51 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 52 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 53 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 54 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 55 | -------------------------------------------------------------------------------- /examples/angularjs/README.md: -------------------------------------------------------------------------------- 1 | # Passport-UserApp - Example with AngularJS as a front-end 2 | 3 | 4 | 5 | Example with AngularJS as the front-end and Node.js+Passport as the back-end. Authentication to UserApp is handled from the front-end by the [UserApp module](https://github.com/userapp-io/userapp-angular), while authorization to the back-end API is done by providing the session token with a cookie. The [UserApp Passport strategy](https://github.com/userapp-io/passport-userapp) is then validating the session token before authorizing the API calls. 6 | 7 | ## Getting Started 8 | 9 | * Get your UserApp [App Id](https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id-) and replace 'YOUR-USERAPP-APP-ID' in `app.js` and `public/js/app.js` with that id. 10 | 11 | * Install all the dependencies: 12 | 13 | `$ npm install` 14 | 15 | * Start the Node.js server 16 | 17 | `$ node app.js` 18 | 19 | * Browse to `http://localhost:3000` 20 | 21 | * Try to sign up and log in. Two "articles" should load from the back-end. 22 | 23 | ## Help 24 | 25 | Contact us via email at support@userapp.io or visit our [support center](https://help.userapp.io). You can also see the [UserApp documentation](https://app.userapp.io/#/docs/) for more information. 26 | 27 | ## License 28 | 29 | (The MIT License) 30 | 31 | Copyright (c) 2014 UserApp 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining a copy of 34 | this software and associated documentation files (the "Software"), to deal in 35 | the Software without restriction, including without limitation the rights to 36 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 37 | the Software, and to permit persons to whom the Software is furnished to do so, 38 | subject to the following conditions: 39 | 40 | The above copyright notice and this permission notice shall be included in all 41 | copies or substantial portions of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 45 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 46 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 47 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 48 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 49 | -------------------------------------------------------------------------------- /examples/http-basic-auth/README.md: -------------------------------------------------------------------------------- 1 | # Passport-UserApp - Example with AngularJS as a front-end and HTTP Basic Authentication 2 | 3 | 4 | 5 | Example with AngularJS as the front-end and Node.js+Passport as the back-end. Authentication to UserApp is handled from the front-end by the UserApp module, while authorization to the back-end API is done by providing the session token via the HTTP Authentication header. The [UserApp Passport strategy](https://github.com/userapp-io/userapp-angular) is then validating the session token before authorizing the API calls. 6 | 7 | ## Getting Started 8 | 9 | * Get your UserApp [App Id](https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id-) and replace 'YOUR-USERAPP-APP-ID' in `app.js` and `public/js/app.js` with that id. 10 | 11 | * Install all the dependencies: 12 | 13 | `$ npm install` 14 | 15 | * Start the Node.js server 16 | 17 | `$ node app.js` 18 | 19 | * Browse to `http://localhost:3000` 20 | 21 | * Try to sign up and log in. Two "articles" should load from the back-end. 22 | 23 | ## Help 24 | 25 | Contact us via email at support@userapp.io or visit our [support center](https://help.userapp.io). You can also see the [UserApp documentation](https://app.userapp.io/#/docs/) for more information. 26 | 27 | ## License 28 | 29 | (The MIT License) 30 | 31 | Copyright (c) 2014 UserApp 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining a copy of 34 | this software and associated documentation files (the "Software"), to deal in 35 | the Software without restriction, including without limitation the rights to 36 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 37 | the Software, and to permit persons to whom the Software is furnished to do so, 38 | subject to the following conditions: 39 | 40 | The above copyright notice and this permission notice shall be included in all 41 | copies or substantial portions of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 45 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 46 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 47 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 48 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 49 | -------------------------------------------------------------------------------- /examples/angularjs/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | http = require('http'), 3 | passport = require('passport'), 4 | flash = require('connect-flash'), 5 | _ = require('underscore'), 6 | UserAppStrategy = require('passport-userapp').Strategy; 7 | 8 | // Local storage for our users and their articles 9 | var users = []; 10 | var articles = [{ 11 | id: '1', 12 | title: 'Title 1', 13 | body: 'Body 1' 14 | },{ 15 | id: '2', 16 | title: 'Title 2', 17 | body: 'Body 2' 18 | }]; 19 | 20 | // Passport session setup 21 | passport.serializeUser(function (user, done) { 22 | done(null, user.username); 23 | }); 24 | 25 | passport.deserializeUser(function (username, done) { 26 | var user = _.find(users, function (user) { 27 | return user.username == username; 28 | }); 29 | if (user === undefined) { 30 | done(new Error('No user with username "' + username + '" found.')); 31 | } else { 32 | done(null, user); 33 | } 34 | }); 35 | 36 | // Use the UserAppStrategy within Passport 37 | passport.use( 38 | new UserAppStrategy({ 39 | appId: 'YOUR-USERAPP-APP-ID' // Your UserApp App Id: https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id- 40 | }, 41 | function (userprofile, done) { 42 | process.nextTick(function () { 43 | var exists = _.any(users, function (user) { 44 | return user.id == userprofile.id; 45 | }); 46 | 47 | if (!exists) { 48 | users.push(userprofile); 49 | } 50 | 51 | return done(null, userprofile); 52 | }); 53 | } 54 | )); 55 | 56 | var app = express(); 57 | 58 | // Configure Express 59 | app.configure(function () { 60 | app.set('port', process.env.PORT || 3000); 61 | app.use(express.logger()); 62 | app.use(express.cookieParser()); 63 | app.use(express.bodyParser()); 64 | app.use(express.methodOverride()); 65 | app.use(express.session({ secret: 'secret' })); 66 | app.use(flash()); 67 | 68 | // Initialize Passport 69 | app.use(passport.initialize()); 70 | app.use(passport.session()); 71 | app.use(app.router); 72 | app.use(express.static(__dirname + '/public')); 73 | }); 74 | 75 | /* 76 | * To get the articles, you need to have a valid UserApp session token in 77 | * a cookie named `ua_session_token` which has been provided by the AngularJS front-end. 78 | * Once the front-end has authenticated to the back-end, the session will be cached 79 | * to save round-trips to UserApp's API. 80 | */ 81 | app.get('/articles', passport.authenticate('userapp'), function (req, res) { 82 | res.send(articles); 83 | }); 84 | 85 | // Start the server 86 | http.createServer(app).listen(app.get('port'), function () { 87 | console.log('Express server listening on port ' + app.get('port')); 88 | }); -------------------------------------------------------------------------------- /examples/http-basic-auth/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | http = require('http'), 3 | passport = require('passport'), 4 | flash = require('connect-flash'), 5 | _ = require('underscore'), 6 | UserAppStrategy = require('passport-userapp').Strategy; 7 | 8 | // Local storage for our users and their articles 9 | var users = []; 10 | var articles = [{ 11 | id: '1', 12 | title: 'Title 1', 13 | body: 'Body 1' 14 | },{ 15 | id: '2', 16 | title: 'Title 2', 17 | body: 'Body 2' 18 | }]; 19 | 20 | // Passport session setup 21 | passport.serializeUser(function (user, done) { 22 | done(null, user.username); 23 | }); 24 | 25 | passport.deserializeUser(function (username, done) { 26 | var user = _.find(users, function (user) { 27 | return user.username == username; 28 | }); 29 | if (user === undefined) { 30 | done(new Error('No user with username "' + username + '" found.')); 31 | } else { 32 | done(null, user); 33 | } 34 | }); 35 | 36 | // Use the UserAppStrategy within Passport 37 | passport.use( 38 | new UserAppStrategy({ 39 | appId: 'YOUR-USERAPP-APP-ID' // Your UserApp App Id: https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id- 40 | }, 41 | function (userprofile, done) { 42 | process.nextTick(function () { 43 | var exists = _.any(users, function (user) { 44 | return user.id == userprofile.id; 45 | }); 46 | 47 | if (!exists) { 48 | users.push(userprofile); 49 | } 50 | 51 | return done(null, userprofile); 52 | }); 53 | } 54 | )); 55 | 56 | var app = express(); 57 | 58 | // Configure Express 59 | app.configure(function () { 60 | app.set('port', process.env.PORT || 3000); 61 | app.use(express.logger()); 62 | app.use(express.cookieParser()); 63 | app.use(express.bodyParser()); 64 | app.use(express.methodOverride()); 65 | app.use(express.session({ secret: 'secret' })); 66 | app.use(flash()); 67 | 68 | // Initialize Passport 69 | app.use(passport.initialize()); 70 | app.use(passport.session()); 71 | app.use(app.router); 72 | app.use(express.static(__dirname + '/public')); 73 | }); 74 | 75 | /* 76 | * To get the articles, you need to provide a valid UserApp session token in 77 | * the password field in the HTTP Basic Authentication header, which has been provided by the AngularJS front-end. 78 | * Once the front-end has authenticated to the back-end, the session will be cached 79 | * to save round-trips to UserApp's API. 80 | */ 81 | app.get('/articles', passport.authenticate('userapp'), function (req, res) { 82 | res.send(articles); 83 | }); 84 | 85 | // Start the server 86 | http.createServer(app).listen(app.get('port'), function () { 87 | console.log('Express server listening on port ' + app.get('port')); 88 | }); -------------------------------------------------------------------------------- /examples/stateless-login/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | http = require('http'), 3 | passport = require('passport'), 4 | flash = require('connect-flash'), 5 | _ = require('underscore'), 6 | UserAppStrategy = require('passport-userapp').Strategy; 7 | 8 | var users = []; 9 | 10 | // Passport session setup 11 | passport.serializeUser(function (user, done) { 12 | done(null, user.username); 13 | }); 14 | 15 | passport.deserializeUser(function (username, done) { 16 | var user = _.find(users, function (user) { 17 | return user.username == username; 18 | }); 19 | if (user === undefined) { 20 | done(new Error('No user with username "' + username + '" found.')); 21 | } else { 22 | done(null, user); 23 | } 24 | }); 25 | 26 | // Use the UserAppStrategy within Passport 27 | passport.use( 28 | new UserAppStrategy({ 29 | appId: 'YOUR-USERAPP-APP-ID' // Your UserApp App Id: https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id- 30 | }, 31 | function (userprofile, done) { 32 | process.nextTick(function () { 33 | var exists = _.any(users, function (user) { 34 | return user.id == userprofile.id; 35 | }); 36 | 37 | if (!exists) { 38 | users.push(userprofile); 39 | } 40 | 41 | return done(null, userprofile); 42 | }); 43 | } 44 | )); 45 | 46 | var app = express(); 47 | 48 | // Configure Express 49 | app.configure(function () { 50 | app.set('port', process.env.PORT || 3000); 51 | app.set('views', __dirname + '/views'); 52 | app.set('view engine', 'ejs'); 53 | app.engine('ejs', require('ejs-locals')); 54 | app.use(express.logger()); 55 | app.use(express.cookieParser()); 56 | app.use(express.bodyParser()); 57 | app.use(express.methodOverride()); 58 | app.use(express.session({ secret: 'secret' })); 59 | app.use(flash()); 60 | 61 | // Initialize Passport 62 | app.use(passport.initialize()); 63 | app.use(passport.session()); 64 | app.use(app.router); 65 | app.use(express.static(__dirname + '/../../public')); 66 | }); 67 | 68 | app.get('/', passport.authenticate('userapp', { failureRedirect: '/login' }), function (req, res) { 69 | res.render('index', { user:req.user }); 70 | }); 71 | 72 | app.get('/account', passport.authenticate('userapp', { failureRedirect: '/login' }), function (req, res) { 73 | res.render('account', { user:req.user }); 74 | }); 75 | 76 | app.get('/login', function (req, res) { 77 | res.render('login', { user:req.user, message:req.flash('error') }); 78 | }); 79 | 80 | // POST /login 81 | app.post('/login', 82 | passport.authenticate('userapp', { failureRedirect: '/login', failureFlash: 'Invalid username or password.'}), 83 | function (req, res) { 84 | res.cookie('ua_session_token', req.user.token); 85 | res.redirect('/'); 86 | } 87 | ); 88 | 89 | // GET /logout 90 | app.get('/logout', function (req, res) { 91 | req.logout(); 92 | res.clearCookie('ua_session_token'); 93 | res.redirect('/'); 94 | }); 95 | 96 | http.createServer(app).listen(app.get('port'), function () { 97 | console.log('Express server listening on port ' + app.get('port')); 98 | }); -------------------------------------------------------------------------------- /examples/login/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | http = require('http'), 3 | passport = require('passport'), 4 | flash = require('connect-flash'), 5 | _ = require('underscore'), 6 | UserAppStrategy = require('passport-userapp').Strategy; 7 | 8 | var users = []; 9 | 10 | // Passport session setup 11 | passport.serializeUser(function (user, done) { 12 | done(null, user.username); 13 | }); 14 | 15 | passport.deserializeUser(function (username, done) { 16 | var user = _.find(users, function (user) { 17 | return user.username == username; 18 | }); 19 | if (user === undefined) { 20 | done(new Error('No user with username "' + username + '" found.')); 21 | } else { 22 | done(null, user); 23 | } 24 | }); 25 | 26 | // Use the UserAppStrategy within Passport 27 | passport.use( 28 | new UserAppStrategy({ 29 | appId: 'YOUR-USERAPP-APP-ID' // Your UserApp App Id: https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id- 30 | }, 31 | function (userprofile, done) { 32 | process.nextTick(function () { 33 | var exists = _.any(users, function (user) { 34 | return user.id == userprofile.id; 35 | }); 36 | 37 | if (!exists) { 38 | users.push(userprofile); 39 | } 40 | 41 | return done(null, userprofile); 42 | }); 43 | } 44 | )); 45 | 46 | var app = express(); 47 | 48 | // Configure Express 49 | app.configure(function () { 50 | app.set('port', process.env.PORT || 3000); 51 | app.set('views', __dirname + '/views'); 52 | app.set('view engine', 'ejs'); 53 | app.engine('ejs', require('ejs-locals')); 54 | app.use(express.logger()); 55 | app.use(express.cookieParser()); 56 | app.use(express.bodyParser()); 57 | app.use(express.methodOverride()); 58 | app.use(express.session({ secret: 'secret' })); 59 | app.use(flash()); 60 | 61 | // Initialize Passport 62 | app.use(passport.initialize()); 63 | app.use(passport.session()); 64 | app.use(app.router); 65 | app.use(express.static(__dirname + '/../../public')); 66 | }); 67 | 68 | app.get('/', function (req, res) { 69 | res.render('index', { user:req.user }); 70 | }); 71 | 72 | app.get('/account', ensureAuthenticated, function (req, res) { 73 | res.render('account', { user:req.user }); 74 | }); 75 | 76 | app.get('/login', function (req, res) { 77 | res.render('login', { user:req.user, message:req.flash('error') }); 78 | }); 79 | 80 | // POST /login 81 | app.post('/login', 82 | passport.authenticate('userapp', { failureRedirect: '/login', failureFlash: 'Invalid username or password.'}), 83 | function (req, res) { 84 | res.redirect('/'); 85 | } 86 | ); 87 | 88 | // GET /logout 89 | app.get('/logout', function (req, res) { 90 | req.logout(); 91 | res.redirect('/'); 92 | }); 93 | 94 | http.createServer(app).listen(app.get('port'), function () { 95 | console.log('Express server listening on port ' + app.get('port')); 96 | }); 97 | 98 | // Simple route middleware to ensure user is authenticated 99 | function ensureAuthenticated(req, res, next) { 100 | if (req.isAuthenticated()) { 101 | return next(); 102 | } 103 | res.redirect('/login'); 104 | } 105 | -------------------------------------------------------------------------------- /examples/http-basic-auth/public/js/services.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* Services */ 4 | 5 | 6 | // Demonstrate how to register services 7 | // In this case it is a simple value service. 8 | angular.module('myApp.services', []) 9 | .value('version', '0.1') 10 | .factory('Base64', function() { 11 | var keyStr = 'ABCDEFGHIJKLMNOP' + 12 | 'QRSTUVWXYZabcdef' + 13 | 'ghijklmnopqrstuv' + 14 | 'wxyz0123456789+/' + 15 | '='; 16 | return { 17 | encode: function (input) { 18 | var output = ""; 19 | var chr1, chr2, chr3 = ""; 20 | var enc1, enc2, enc3, enc4 = ""; 21 | var i = 0; 22 | 23 | do { 24 | chr1 = input.charCodeAt(i++); 25 | chr2 = input.charCodeAt(i++); 26 | chr3 = input.charCodeAt(i++); 27 | 28 | enc1 = chr1 >> 2; 29 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 30 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 31 | enc4 = chr3 & 63; 32 | 33 | if (isNaN(chr2)) { 34 | enc3 = enc4 = 64; 35 | } else if (isNaN(chr3)) { 36 | enc4 = 64; 37 | } 38 | 39 | output = output + 40 | keyStr.charAt(enc1) + 41 | keyStr.charAt(enc2) + 42 | keyStr.charAt(enc3) + 43 | keyStr.charAt(enc4); 44 | chr1 = chr2 = chr3 = ""; 45 | enc1 = enc2 = enc3 = enc4 = ""; 46 | } while (i < input.length); 47 | 48 | return output; 49 | }, 50 | 51 | decode: function (input) { 52 | var output = ""; 53 | var chr1, chr2, chr3 = ""; 54 | var enc1, enc2, enc3, enc4 = ""; 55 | var i = 0; 56 | 57 | // remove all characters that are not A-Z, a-z, 0-9, +, /, or = 58 | var base64test = /[^A-Za-z0-9\+\/\=]/g; 59 | if (base64test.exec(input)) { 60 | alert("There were invalid base64 characters in the input text.\n" + 61 | "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" + 62 | "Expect errors in decoding."); 63 | } 64 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 65 | 66 | do { 67 | enc1 = keyStr.indexOf(input.charAt(i++)); 68 | enc2 = keyStr.indexOf(input.charAt(i++)); 69 | enc3 = keyStr.indexOf(input.charAt(i++)); 70 | enc4 = keyStr.indexOf(input.charAt(i++)); 71 | 72 | chr1 = (enc1 << 2) | (enc2 >> 4); 73 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 74 | chr3 = ((enc3 & 3) << 6) | enc4; 75 | 76 | output = output + String.fromCharCode(chr1); 77 | 78 | if (enc3 != 64) { 79 | output = output + String.fromCharCode(chr2); 80 | } 81 | if (enc4 != 64) { 82 | output = output + String.fromCharCode(chr3); 83 | } 84 | 85 | chr1 = chr2 = chr3 = ""; 86 | enc1 = enc2 = enc3 = enc4 = ""; 87 | 88 | } while (i < input.length); 89 | 90 | return output; 91 | } 92 | }; 93 | }); -------------------------------------------------------------------------------- /examples/angularjs/public/lib/angular/angular-route.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.3 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(t,c,A){'use strict';function x(r,m,d,b,h){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(l,z,k,B,w){function v(){g&&(g.$destroy(),g=null);q&&(h.leave(q),q=null)}function u(){var a=r.current&&r.current.locals,e=a&&a.$template;if(e){var y=l.$new(),s=w(y,c.noop);s.html(e);h.enter(s,null,q||z,function(){!c.isDefined(n)||n&&!l.$eval(n)||m()});v();var e=d(s.contents()),f=r.current;g=f.scope=y;q=s;f.controller&&(a.$scope=g,a=b(f.controller,a),f.controllerAs&& 7 | (g[f.controllerAs]=a),s.data("$ngControllerController",a),s.children().data("$ngControllerController",a));e(g);g.$emit("$viewContentLoaded");g.$eval(p)}else v()}var g,q,n=k.autoscroll,p=k.onload||"";l.$on("$routeChangeSuccess",u);u()}}}t=c.module("ngRoute",["ng"]).provider("$route",function(){function r(b,h){return c.extend(new (c.extend(function(){},{prototype:b})),h)}function m(b,c){var l=c.caseInsensitiveMatch,d={originalPath:b,regexp:b},k=d.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g, 8 | function(b,c,h,d){b="?"===d?d:null;d="*"===d?d:null;k.push({name:h,optional:!!b});c=c||"";return""+(b?"":c)+"(?:"+(b?c:"")+(d&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");d.regexp=RegExp("^"+b+"$",l?"i":"");return d}var d={};this.when=function(b,h){d[b]=c.extend({reloadOnSearch:!0},h,b&&m(b,h));if(b){var l="/"==b[b.length-1]?b.substr(0,b.length-1):b+"/";d[l]=c.extend({redirectTo:b},m(l,h))}return this};this.otherwise=function(b){this.when(null,b);return this};this.$get= 9 | ["$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(b,h,l,m,k,t,w,v){function u(){var a=g(),e=p.current;if(a&&e&&a.$$route===e.$$route&&c.equals(a.pathParams,e.pathParams)&&!a.reloadOnSearch&&!n)e.params=a.params,c.copy(e.params,l),b.$broadcast("$routeUpdate",e);else if(a||e)n=!1,b.$broadcast("$routeChangeStart",a,e),(p.current=a)&&a.redirectTo&&(c.isString(a.redirectTo)?h.path(q(a.redirectTo,a.params)).search(a.params).replace():h.url(a.redirectTo(a.pathParams, 10 | h.path(),h.search())).replace()),m.when(a).then(function(){if(a){var b=c.extend({},a.resolve),e,f;c.forEach(b,function(a,e){b[e]=c.isString(a)?k.get(a):k.invoke(a)});c.isDefined(e=a.template)?c.isFunction(e)&&(e=e(a.params)):c.isDefined(f=a.templateUrl)&&(c.isFunction(f)&&(f=f(a.params)),f=v.getTrustedResourceUrl(f),c.isDefined(f)&&(a.loadedTemplateUrl=f,e=t.get(f,{cache:w}).then(function(a){return a.data})));c.isDefined(e)&&(b.$template=e);return m.all(b)}}).then(function(d){a==p.current&&(a&&(a.locals= 11 | d,c.copy(a.params,l)),b.$broadcast("$routeChangeSuccess",a,e))},function(c){a==p.current&&b.$broadcast("$routeChangeError",a,e,c)})}function g(){var a,b;c.forEach(d,function(d,l){var f;if(f=!b){var g=h.path();f=d.keys;var m={};if(d.regexp)if(g=d.regexp.exec(g)){for(var k=1,q=g.length;k 0) { 168 | self._verify(parseProfile(users[0]), verified); 169 | } else { 170 | self._verify(false, verified); 171 | } 172 | }); 173 | } 174 | 175 | if (sessionToken && req.isAuthenticated()) { 176 | self._verify(req.user, verified); 177 | return; 178 | } 179 | 180 | if (sessionToken && !username) { 181 | UserApp.setToken(sessionToken); 182 | getUser(); 183 | } else { 184 | UserApp.setToken(null); 185 | UserApp.User.login({ login: username, password: password }, function(error) { 186 | if (error) { 187 | self._verify(false, verified); 188 | } else { 189 | getUser(); 190 | } 191 | }); 192 | } 193 | }; 194 | 195 | /** 196 | * Authentication challenge. 197 | * 198 | * @api private 199 | */ 200 | Strategy.prototype._challenge = function() { 201 | return 'Basic realm="' + this._realm + '"'; 202 | } 203 | 204 | /** 205 | * Expose `Strategy`. 206 | */ 207 | module.exports = Strategy; 208 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Passport-UserApp 2 | 3 | Password and token authentication strategy using [UserApp](https://www.userapp.io) for [Passport](http://passportjs.org/). 4 | 5 | *UserApp is a cloud-based user management API for web apps with the purpose to relieve developers from having to program logic for user authentication, sign-up, invoicing, feature/property/permission management, and more.* 6 | 7 | This module lets you authenticate using either a username and password or a session token in your Node.js 8 | applications. By plugging into Passport, UserApp authentication can be easily and 9 | unobtrusively integrated into any application or framework that supports 10 | [Connect](http://www.senchalabs.org/connect/)-style middleware, including 11 | [Express](http://expressjs.com/). 12 | 13 | ## Installation 14 | 15 | $ npm install passport-userapp 16 | 17 | ## Usage 18 | 19 | #### Configure Strategy 20 | 21 | The userapp authentication strategy authenticates users using either a username and 22 | password or a session token via a REST call to UserApp. The strategy requires a `verify` callback, which accepts these 23 | credentials and calls `done` providing a user. To be able to use this strategy, you need a [UserApp account](https://app.userapp.io/#/sign-up/), with an [App Id](https://help.userapp.io/customer/portal/articles/1322336-how-do-i-find-my-app-id-). 24 | 25 | ```javascript 26 | passport.use(new UserAppStrategy({ 27 | appId: 'YOU-USERAPP-APP-ID' 28 | }, 29 | function (userprofile, done) { 30 | Users.findOrCreate(userprofile, function(err,user) { 31 | if(err) return done(err); 32 | return done(null, user); 33 | }); 34 | } 35 | )); 36 | ``` 37 | 38 | #### Authenticate Requests Using Username/Password 39 | 40 | Use `passport.authenticate()`, specifying the `'userapp'` strategy, to 41 | authenticate requests using a username and password. The username and password should be sent as POST parameters with the request. 42 | 43 | For example, as route middleware in an [Express](http://expressjs.com/) 44 | application: 45 | 46 | ```javascript 47 | app.post('/login', 48 | passport.authenticate('userapp', { failureRedirect: '/login' }), 49 | function(req, res) { 50 | res.redirect('/'); 51 | }); 52 | ``` 53 | 54 | **Stateless Server Sessions** 55 | 56 | To make your server stateless (i.e. you could restart your server without logging out your users), just save the UserApp session token in a cookie named `ua_session_token`: 57 | 58 | ```javascript 59 | app.post('/login', 60 | passport.authenticate('userapp', { failureRedirect: '/login' }), 61 | function(req, res) { 62 | res.cookie('ua_session_token', req.user.token); 63 | res.redirect('/'); 64 | }); 65 | ``` 66 | 67 | Don't forget to delete it when logging out: 68 | 69 | ```javascript 70 | app.get('/logout', function (req, res) { 71 | req.logout(); 72 | res.clearCookie('ua_session_token'); 73 | res.redirect('/'); 74 | }); 75 | ``` 76 | 77 | And to protect your routes, use the `passport.authenticate()` method, like this: 78 | 79 | ```javascript 80 | app.get('/account', 81 | passport.authenticate('userapp', { failureRedirect: '/login' }), 82 | function (req, res) { 83 | res.render('account', { user:req.user }); 84 | }); 85 | ``` 86 | 87 | #### Authenticate Requests Using a Session Token 88 | 89 | Use `passport.authenticate()`, specifying the `'userapp'` strategy, to 90 | authenticate requests using a session token. The token should be sent as a cookie named `ua_session_token` (automatically set by the front-end integrations such as the [AngularJS module](https://github.com/userapp-io/userapp-angular)). 91 | 92 | For example, as route middleware in an [Express](http://expressjs.com/) 93 | application: 94 | 95 | ```javascript 96 | app.post('/api/call', passport.authenticate('userapp'), 97 | function(req, res) { 98 | // Return some relevant data, for example the logged in user, articles, etc. 99 | res.send({ user: req.user }); 100 | }); 101 | ``` 102 | 103 | #### Authenticate Requests Using HTTP Basic Authentication 104 | 105 | Use `passport.authenticate()`, specifying the `'userapp'` strategy, to 106 | authenticate requests using HTTP Basic Authentication. It can be used in two ways; 1) with a username and password, or 2) by leaving username empty and setting password to a token. 107 | 108 | #### User Profile 109 | 110 | The user profile follows the [Passport Profile Schema](http://passportjs.org/guide/profile/) when available. Some fields are added to contain all information from the [UserApp User entity](https://app.userapp.io/#/docs/user/#properties). 111 | 112 | ```javascript 113 | { 114 | provider: 'userapp', 115 | id: 'user_id', 116 | username: 'login', 117 | name: { familyName: 'last_name', givenName: 'first_name' }, 118 | email: 'email', 119 | emails: [ { value: 'email' } ], 120 | permissions: { permissionName: { value: boolean, override: boolean } }, 121 | features: { featureName: { value: boolean, override: boolean } }, 122 | properties: { propertyName: { value: mixed, override: boolean } }, 123 | subscription: { price_list_id: 'string', plan_id: 'string', override: boolean }, 124 | lastLoginAt: unix_timestamp, 125 | updatedAt: unix_timestamp, 126 | createdAt: unix_timestamp, 127 | token: 'session token', 128 | _raw: { /* raw UserApp User profile */ } 129 | } 130 | ``` 131 | 132 | Please note that when working with the [UserApp API](https://app.userapp.io/#/docs/), you will need to create a new user object according to the [User entity](https://app.userapp.io/#/docs/user/#properties). For example `username` => `login`. 133 | 134 | ## Examples 135 | 136 | For a complete, working example, refer to the [login example](https://github.com/userapp-io/passport-userapp/tree/master/examples/login) or the [signup-login example](https://github.com/userapp-io/passport-userapp/tree/master/examples/signup-login). 137 | 138 | For an example using AngularJS as front-end, refer to the [AngularJS example](https://github.com/userapp-io/passport-userapp/tree/master/examples/angularjs). 139 | 140 | For an example with stateless sessions, refer to the [stateless-login example](https://github.com/userapp-io/passport-userapp/tree/master/examples/stateless-login). 141 | 142 | For an example with HTTP Basic Authentication, refer to the [http-basic-auth example](https://github.com/userapp-io/passport-userapp/tree/master/examples/http-basic-auth). 143 | 144 | ## Related Modules 145 | 146 | - [userapp-nodejs](https://github.com/userapp-io/userapp-nodejs) — Node.js client for accessing the UserApp API 147 | 148 | ## Help 149 | 150 | Contact us via email at support@userapp.io or visit our [support center](https://help.userapp.io). 151 | 152 | ## Credits 153 | 154 | - [Timothy E. Johansson](https://github.com/timothyej) 155 | - [Charlton Roberts](https://github.com/charltoons) 156 | 157 | ## License 158 | 159 | (The MIT License) 160 | 161 | Copyright (c) 2014 UserApp 162 | 163 | Permission is hereby granted, free of charge, to any person obtaining a copy of 164 | this software and associated documentation files (the "Software"), to deal in 165 | the Software without restriction, including without limitation the rights to 166 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 167 | the Software, and to permit persons to whom the Software is furnished to do so, 168 | subject to the following conditions: 169 | 170 | The above copyright notice and this permission notice shall be included in all 171 | copies or substantial portions of the Software. 172 | 173 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 175 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 176 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 177 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 178 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 179 | -------------------------------------------------------------------------------- /examples/angularjs/public/lib/angular/angular.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.3 3 | (c) 2010-2014 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(X,O,r){'use strict';function A(b){return function(){var a=arguments[0],c,a="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.2.3/"+(b?b+"/":"")+a;for(c=1;c").append(b).html();try{return 3===b[0].nodeType?t(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+t(b)})}catch(d){return t(c)}}function Ub(b){try{return decodeURIComponent(b)}catch(a){}} 15 | function Vb(b){var a={},c,d;q((b||"").split("&"),function(b){b&&(c=b.split("="),d=Ub(c[0]),B(d)&&(b=B(c[1])?Ub(c[1]):!0,a[d]?K(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Wb(b){var a=[];q(b,function(b,d){K(b)?q(b,function(b){a.push(ua(d,!0)+(!0===b?"":"="+ua(b,!0)))}):a.push(ua(d,!0)+(!0===b?"":"="+ua(b,!0)))});return a.length?a.join("&"):""}function sb(b){return ua(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ua(b,a){return encodeURIComponent(b).replace(/%40/gi, 16 | "@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,a?"%20":"+")}function Rc(b,a){function c(a){a&&d.push(a)}var d=[b],e,g,f=["ng:app","ng-app","x-ng-app","data-ng-app"],h=/\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;q(f,function(a){f[a]=!0;c(O.getElementById(a));a=a.replace(":","\\:");b.querySelectorAll&&(q(b.querySelectorAll("."+a),c),q(b.querySelectorAll("."+a+"\\:"),c),q(b.querySelectorAll("["+a+"]"),c))});q(d,function(a){if(!e){var b=h.exec(" "+a.className+" ");b?(e=a,g= 17 | (b[2]||"").replace(/\s+/g,",")):q(a.attributes,function(b){!e&&f[b.name]&&(e=a,g=b.value)})}});e&&a(e,g?[g]:[])}function Xb(b,a){var c=function(){b=x(b);if(b.injector()){var c=b[0]===O?"document":ha(b);throw Ma("btstrpd",c);}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);a.unshift("ng");c=Yb(a);c.invoke(["$rootScope","$rootElement","$compile","$injector","$animate",function(a,b,c,d,e){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},d=/^NG_DEFER_BOOTSTRAP!/; 18 | if(X&&!d.test(X.name))return c();X.name=X.name.replace(d,"");cb.resumeBootstrap=function(b){q(b,function(b){a.push(b)});c()}}function db(b,a){a=a||"_";return b.replace(Sc,function(b,d){return(d?a:"")+b.toLowerCase()})}function tb(b,a,c){if(!b)throw Ma("areq",a||"?",c||"required");return b}function Oa(b,a,c){c&&K(b)&&(b=b[b.length-1]);tb(I(b),a,"not a function, got "+(b&&"object"==typeof b?b.constructor.name||"Object":typeof b));return b}function va(b,a){if("hasOwnProperty"===b)throw Ma("badname", 19 | a);}function ub(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,g=a.length,f=0;f 
"+b;a.removeChild(a.firstChild);yb(this,a.childNodes);x(O.createDocumentFragment()).append(this)}else yb(this,b)}function zb(b){return b.cloneNode(!0)}function Qa(b){Zb(b);var a=0;for(b=b.childNodes|| 23 | [];a=M?(c.preventDefault= 27 | null,c.stopPropagation=null,c.isDefaultPrevented=null):(delete c.preventDefault,delete c.stopPropagation,delete c.isDefaultPrevented)};c.elem=b;return c}function Ca(b){var a=typeof b,c;"object"==a&&null!==b?"function"==typeof(c=b.$$hashKey)?c=b.$$hashKey():c===r&&(c=b.$$hashKey=Za()):c=b;return a+":"+c}function Sa(b){q(b,this.put,this)}function ec(b){var a,c;"function"==typeof b?(a=b.$inject)||(a=[],b.length&&(c=b.toString().replace(Yc,""),c=c.match(Zc),q(c[1].split($c),function(b){b.replace(ad,function(b, 28 | c,d){a.push(d)})})),b.$inject=a):K(b)?(c=b.length-1,Oa(b[c],"fn"),a=b.slice(0,c)):Oa(b,"fn",!0);return a}function Yb(b){function a(a){return function(b,c){if(V(b))q(b,Pb(a));else return a(b,c)}}function c(a,b){va(a,"service");if(I(b)||K(b))b=n.instantiate(b);if(!b.$get)throw Ta("pget",a);return l[a+h]=b}function d(a,b){return c(a,{$get:b})}function e(a){var b=[],c,d,h,g;q(a,function(a){if(!k.get(a)){k.put(a,!0);try{if(w(a))for(c=Ua(a),b=b.concat(e(c.requires)).concat(c._runBlocks),d=c._invokeQueue, 29 | h=0,g=d.length;h 4096 bytes)!"));else{if(m.cookie!==Z)for(Z=m.cookie,d=Z.split("; "),E={},h=0;hk&&this.remove(p.key),b},get:function(a){var b=l[a];if(b)return e(b),m[a]},remove:function(a){var b=l[a];b&&(b==n&&(n=b.p),b==p&&(p=b.n),g(b.n,b.p),delete l[a],delete m[a],f--)},removeAll:function(){m={};f=0;l={};n=p=null},destroy:function(){l=h=m=null;delete a[b]},info:function(){return F({}, 39 | h,{size:f})}}}var a={};b.info=function(){var b={};q(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function fd(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function gc(b,a){var c={},d="Directive",e=/^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,g=/(([\d\w\-_]+)(?:\:([^;]+))?;?)/,f=/^(on[a-z]+|formaction)$/;this.directive=function m(a,e){va(a,"directive");w(a)?(tb(e,"directiveFactory"),c.hasOwnProperty(a)||(c[a]=[],b.factory(a+d,["$injector","$exceptionHandler", 40 | function(b,d){var e=[];q(c[a],function(c,g){try{var f=b.invoke(c);I(f)?f={compile:ba(f)}:!f.compile&&f.link&&(f.compile=ba(f.link));f.priority=f.priority||0;f.index=g;f.name=f.name||a;f.require=f.require||f.controller&&f.name;f.restrict=f.restrict||"A";e.push(f)}catch(m){d(m)}});return e}])),c[a].push(e)):q(a,Pb(m));return this};this.aHrefSanitizationWhitelist=function(b){return B(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return B(b)? 41 | (a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};this.$get=["$injector","$interpolate","$exceptionHandler","$http","$templateCache","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,l,n,p,s,D,u,Q,z,Y,H){function y(a,b,c,d,e){a instanceof x||(a=x(a));q(a,function(b,c){3==b.nodeType&&b.nodeValue.match(/\S+/)&&(a[c]=x(b).wrap("").parent()[0])});var g=R(a,b,a,c,d,e);return function(b,c,d){tb(b,"scope");var e=c?Da.clone.call(a): 42 | a;q(d,function(a,b){e.data("$"+b+"Controller",a)});d=0;for(var f=e.length;darguments.length&&(b=a,a=r);Ga&&(c=P);return p(a,b,c)}var u,ca,H,R,da,J,P={},Z;u=c===g?d:Pc(d,new Eb(x(g),d.$attr));ca=u.$$element;if(E){var T=/^\s*([@=&])(\??)\s*(\w*)\s*$/;f=x(g);J=e.$new(!0);N&&N===E.$$originalDirective?f.data("$isolateScope",J):f.data("$isolateScopeNoTemplate",J);aa(f,"ng-isolate-scope");q(E.scope,function(a,c){var d=a.match(T)|| 48 | [],g=d[3]||c,f="?"==d[2],d=d[1],m,l,n;J.$$isolateBindings[c]=d+g;switch(d){case "@":u.$observe(g,function(a){J[c]=a});u.$$observers[g].$$scope=e;u[g]&&(J[c]=b(u[g])(e));break;case "=":if(f&&!u[g])break;l=s(u[g]);n=l.assign||function(){m=J[c]=l(e);throw ia("nonassign",u[g],E.name);};m=J[c]=l(e);J.$watch(function(){var a=l(e);a!==J[c]&&(a!==m?m=J[c]=a:n(e,a=m=J[c]));return a});break;case "&":l=s(u[g]);J[c]=function(a){return l(e,a)};break;default:throw ia("iscp",E.name,c,a);}})}Z=p&&y;z&&q(z,function(a){var b= 49 | {$scope:a===E||a.$$isolateScope?J:e,$element:ca,$attrs:u,$transclude:Z},c;da=a.controller;"@"==da&&(da=u[a.name]);c=D(da,b);P[a.name]=c;Ga||ca.data("$"+a.name+"Controller",c);a.controllerAs&&(b.$scope[a.controllerAs]=c)});f=0;for(H=m.length;fG.priority)break;if(t=G.scope)R=R||G,G.templateUrl||(C("new/isolated scope",E,G,v),V(t)&&(E=G));ea=G.name;!G.templateUrl&&G.controller&&(t=G.controller,z=z||{},C("'"+ea+"' controller",z[ea],G,v), 51 | z[ea]=G);if(t=G.transclude)la=!0,G.$$tlb||(C("transclusion",p,G,v),p=G),"element"==t?(Ga=!0,H=G.priority,t=da(c,Va,Fa),v=d.$$element=x(O.createComment(" "+ea+": "+d[ea]+" ")),c=v[0],S(g,x(ta.call(t,0)),c),F=y(t,e,H,f&&f.name,{nonTlbTranscludeDirective:p})):(t=x(zb(c)).contents(),v.html(""),F=y(t,e));if(G.template)if(C("template",N,G,v),N=G,t=I(G.template)?G.template(v,d):G.template,t=hc(t),G.replace){f=G;t=x("
"+$(t)+"
").contents();c=t[0];if(1!=t.length||1!==c.nodeType)throw ia("tplrt", 52 | ea,"");S(g,v,c);M={$attr:{}};t=Z(c,[],M);var W=a.splice(L+1,a.length-(L+1));E&&T(t);a=a.concat(t).concat(W);fc(d,M);M=a.length}else v.html(t);if(G.templateUrl)C("template",N,G,v),N=G,G.replace&&(f=G),Q=B(a.splice(L,a.length-L),v,d,g,F,m,n,{controllerDirectives:z,newIsolateScopeDirective:E,templateDirective:N,nonTlbTranscludeDirective:p}),M=a.length;else if(G.compile)try{A=G.compile(v,d,F),I(A)?u(null,A,Va,Fa):A&&u(A.pre,A.post,Va,Fa)}catch(X){l(X,ha(v))}G.terminal&&(Q.terminal=!0,H=Math.max(H,G.priority))}Q.scope= 53 | R&&!0===R.scope;Q.transclude=la&&F;return Q}function T(a){for(var b=0,c=a.length;bs.priority)&&-1!=s.restrict.indexOf(g)&&(n&&(s=Rb(s,{$$start:n,$$end:p})),b.push(s),k=s)}catch(y){l(y)}}return k}function fc(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;q(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&(d+=("style"===e? 54 | ";":" ")+b[e]),a.$set(e,d,!0,c[e]))});q(b,function(b,g){"class"==g?(aa(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==g?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==g.charAt(0)||a.hasOwnProperty(g)||(a[g]=b,d[g]=c[g])})}function B(a,b,c,d,e,g,f,m){var k=[],l,s,D=b[0],u=a.shift(),y=F({},u,{templateUrl:null,transclude:null,replace:null,$$originalDirective:u}),Y=I(u.templateUrl)?u.templateUrl(b,c):u.templateUrl;b.html("");n.get(z.getTrustedResourceUrl(Y), 55 | {cache:p}).success(function(n){var p,Q;n=hc(n);if(u.replace){n=x("
"+$(n)+"
").contents();p=n[0];if(1!=n.length||1!==p.nodeType)throw ia("tplrt",u.name,Y);n={$attr:{}};S(d,b,p);var H=Z(p,[],n);V(u.scope)&&T(H);a=H.concat(a);fc(c,n)}else p=D,b.html(n);a.unshift(y);l=N(a,p,c,e,b,u,g,f,m);q(d,function(a,c){a==p&&(d[c]=b[0])});for(s=R(b[0].childNodes,e);k.length;){n=k.shift();Q=k.shift();var aa=k.shift(),z=k.shift(),H=b[0];Q!==D&&(H=zb(p),S(aa,x(Q),H));Q=l.transclude?E(n,l.transclude):z;l(s, 56 | n,H,d,Q)}k=null}).error(function(a,b,c,d){throw ia("tpload",d.url);});return function(a,b,c,d,e){k?(k.push(b),k.push(c),k.push(d),k.push(e)):l(s,b,c,d,e)}}function v(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.namea.status?b:n.reject(b)}var d={transformRequest:e.transformRequest, 65 | transformResponse:e.transformResponse},g=function(a){function b(a){var c;q(a,function(b,d){I(b)&&(c=b(),null!=c?a[d]=c:delete a[d])})}var c=e.headers,d=F({},a.headers),g,f,c=F({},c.common,c[t(a.method)]);b(c);b(d);a:for(g in c){a=t(g);for(f in d)if(t(f)===a)continue a;d[g]=c[g]}return d}(a);F(d,a);d.headers=g;d.method=Ha(d.method);(a=Fb(d.url)?b.cookies()[d.xsrfCookieName||e.xsrfCookieName]:r)&&(g[d.xsrfHeaderName||e.xsrfHeaderName]=a);var h=[function(a){g=a.headers;var b=lc(a.data,kc(g),a.transformRequest); 66 | C(a.data)&&q(g,function(a,b){"content-type"===t(b)&&delete g[b]});C(a.withCredentials)&&!C(e.withCredentials)&&(a.withCredentials=e.withCredentials);return D(a,b,g).then(c,c)},r],f=n.when(d);for(q(z,function(a){(a.request||a.requestError)&&h.unshift(a.request,a.requestError);(a.response||a.responseError)&&h.push(a.response,a.responseError)});h.length;){a=h.shift();var k=h.shift(),f=f.then(a,k)}f.success=function(a){f.then(function(b){a(b.data,b.status,b.headers,d)});return f};f.error=function(a){f.then(null, 67 | function(b){a(b.data,b.status,b.headers,d)});return f};return f}function D(b,c,g){function f(a,b,c){q&&(200<=a&&300>a?q.put(r,[a,b,jc(c)]):q.remove(r));m(b,a,c);d.$$phase||d.$apply()}function m(a,c,d){c=Math.max(c,0);(200<=c&&300>c?p.resolve:p.reject)({data:a,status:c,headers:kc(d),config:b})}function k(){var a=bb(s.pendingRequests,b);-1!==a&&s.pendingRequests.splice(a,1)}var p=n.defer(),D=p.promise,q,z,r=u(b.url,b.params);s.pendingRequests.push(b);D.then(k,k);(b.cache||e.cache)&&(!1!==b.cache&&"GET"== 68 | b.method)&&(q=V(b.cache)?b.cache:V(e.cache)?e.cache:Q);if(q)if(z=q.get(r),B(z)){if(z.then)return z.then(k,k),z;K(z)?m(z[1],z[0],ga(z[2])):m(z,200,{})}else q.put(r,D);C(z)&&a(b.method,r,c,f,g,b.timeout,b.withCredentials,b.responseType);return D}function u(a,b){if(!b)return a;var c=[];Mc(b,function(a,b){null===a||C(a)||(K(a)||(a=[a]),q(a,function(a){V(a)&&(a=oa(a));c.push(ua(b)+"="+ua(a))}))});return a+(-1==a.indexOf("?")?"?":"&")+c.join("&")}var Q=c("$http"),z=[];q(g,function(a){z.unshift(w(a)?p.get(a): 69 | p.invoke(a))});q(f,function(a,b){var c=w(a)?p.get(a):p.invoke(a);z.splice(b,0,{response:function(a){return c(n.when(a))},responseError:function(a){return c(n.reject(a))}})});s.pendingRequests=[];(function(a){q(arguments,function(a){s[a]=function(b,c){return s(F(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){q(arguments,function(a){s[a]=function(b,c,d){return s(F(d||{},{method:a,url:b,data:c}))}})})("post","put");s.defaults=e;return s}]}function ld(){this.$get=["$browser", 70 | "$window","$document",function(b,a,c){return md(b,nd,b.defer,a.angular.callbacks,c[0])}]}function md(b,a,c,d,e){function g(a,b){var c=e.createElement("script"),d=function(){c.onreadystatechange=c.onload=c.onerror=null;e.body.removeChild(c);b&&b()};c.type="text/javascript";c.src=a;M&&8>=M?c.onreadystatechange=function(){/loaded|complete/.test(c.readyState)&&d()}:c.onload=c.onerror=function(){d()};e.body.appendChild(c);return d}var f=-1;return function(e,m,k,l,n,p,s,D){function u(){z=f;H&&H();y&&y.abort()} 71 | function Q(a,d,e,g){var f=wa(m).protocol;aa&&c.cancel(aa);H=y=null;d="file"==f&&0===d?e?200:404:d;a(1223==d?204:d,e,g);b.$$completeOutstandingRequest(v)}var z;b.$$incOutstandingRequestCount();m=m||b.url();if("jsonp"==t(e)){var r="_"+(d.counter++).toString(36);d[r]=function(a){d[r].data=a};var H=g(m.replace("JSON_CALLBACK","angular.callbacks."+r),function(){d[r].data?Q(l,200,d[r].data):Q(l,z||-2);delete d[r]})}else{var y=new a;y.open(e,m,!0);q(n,function(a,b){B(a)&&y.setRequestHeader(b,a)});y.onreadystatechange= 72 | function(){if(4==y.readyState){var a=null,b=null;z!==f&&(a=y.getAllResponseHeaders(),b=y.responseType?y.response:y.responseText);Q(l,z||y.status,b,a)}};s&&(y.withCredentials=!0);D&&(y.responseType=D);y.send(k||null)}if(0=h&&(n.resolve(s),l(p.$$intervalId),delete e[p.$$intervalId]);D||b.$apply()},f);e[p.$$intervalId]=n;return p} 75 | var e={};d.cancel=function(a){return a&&a.$$intervalId in e?(e[a.$$intervalId].reject("canceled"),clearInterval(a.$$intervalId),delete e[a.$$intervalId],!0):!1};return d}]}function qd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "), 76 | SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function nc(b){b=b.split("/");for(var a=b.length;a--;)b[a]= 77 | sb(b[a]);return b.join("/")}function oc(b,a,c){b=wa(b,c);a.$$protocol=b.protocol;a.$$host=b.hostname;a.$$port=S(b.port)||rd[b.protocol]||null}function pc(b,a,c){var d="/"!==b.charAt(0);d&&(b="/"+b);b=wa(b,c);a.$$path=decodeURIComponent(d&&"/"===b.pathname.charAt(0)?b.pathname.substring(1):b.pathname);a.$$search=Vb(b.search);a.$$hash=decodeURIComponent(b.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function na(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Wa(b){var a= 78 | b.indexOf("#");return-1==a?b:b.substr(0,a)}function Gb(b){return b.substr(0,Wa(b).lastIndexOf("/")+1)}function qc(b,a){this.$$html5=!0;a=a||"";var c=Gb(b);oc(b,this,b);this.$$parse=function(a){var e=na(c,a);if(!w(e))throw Hb("ipthprfx",a,c);pc(e,this,b);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Wb(this.$$search),b=this.$$hash?"#"+sb(this.$$hash):"";this.$$url=nc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$rewrite=function(d){var e; 79 | if((e=na(b,d))!==r)return d=e,(e=na(a,e))!==r?c+(na("/",e)||e):b+d;if((e=na(c,d))!==r)return c+e;if(c==d+"/")return c}}function Ib(b,a){var c=Gb(b);oc(b,this,b);this.$$parse=function(d){var e=na(b,d)||na(c,d),e="#"==e.charAt(0)?na(a,e):this.$$html5?e:"";if(!w(e))throw Hb("ihshprfx",d,a);pc(e,this,b);d=this.$$path;var g=/^\/?.*?:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));g.exec(e)||(d=(e=g.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Wb(this.$$search),e=this.$$hash? 80 | "#"+sb(this.$$hash):"";this.$$url=nc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$rewrite=function(a){if(Wa(b)==Wa(a))return a}}function rc(b,a){this.$$html5=!0;Ib.apply(this,arguments);var c=Gb(b);this.$$rewrite=function(d){var e;if(b==Wa(d))return d;if(e=na(c,d))return b+a+e;if(c===d+"/")return c}}function hb(b){return function(){return this[b]}}function sc(b,a){return function(c){if(C(c))return this[b];this[b]=a(c);this.$$compose();return this}}function sd(){var b= 81 | "",a=!1;this.hashPrefix=function(a){return B(a)?(b=a,this):b};this.html5Mode=function(b){return B(b)?(a=b,this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,g){function f(a){c.$broadcast("$locationChangeSuccess",h.absUrl(),a)}var h,m=d.baseHref(),k=d.url();a?(m=k.substring(0,k.indexOf("/",k.indexOf("//")+2))+(m||"/"),e=e.history?qc:rc):(m=Wa(k),e=Ib);h=new e(m,"#"+b);h.$$parse(h.$$rewrite(k));g.on("click",function(a){if(!a.ctrlKey&&!a.metaKey&&2!=a.which){for(var b= 82 | x(a.target);"a"!==t(b[0].nodeName);)if(b[0]===g[0]||!(b=b.parent())[0])return;var e=b.prop("href"),f=h.$$rewrite(e);e&&(!b.attr("target")&&f&&!a.isDefaultPrevented())&&(a.preventDefault(),f!=d.url()&&(h.$$parse(f),c.$apply(),X.angular["ff-684208-preventDefault"]=!0))}});h.absUrl()!=k&&d.url(h.absUrl(),!0);d.onUrlChange(function(a){h.absUrl()!=a&&(c.$broadcast("$locationChangeStart",a,h.absUrl()).defaultPrevented?d.url(h.absUrl()):(c.$evalAsync(function(){var b=h.absUrl();h.$$parse(a);f(b)}),c.$$phase|| 83 | c.$digest()))});var l=0;c.$watch(function(){var a=d.url(),b=h.$$replace;l&&a==h.absUrl()||(l++,c.$evalAsync(function(){c.$broadcast("$locationChangeStart",h.absUrl(),a).defaultPrevented?h.$$parse(a):(d.url(h.absUrl(),b),f(a))}));h.$$replace=!1;return l});return h}]}function td(){var b=!0,a=this;this.debugEnabled=function(a){return B(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack: 84 | a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;return e.apply?function(){var a=[];q(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function pa(b,a){if("constructor"===b)throw xa("isecfld",a);return b}function Xa(b,a){if(b&&b.constructor=== 85 | b)throw xa("isecfn",a);if(b&&b.document&&b.location&&b.alert&&b.setInterval)throw xa("isecwindow",a);if(b&&(b.nodeName||b.on&&b.find))throw xa("isecdom",a);return b}function ib(b,a,c,d,e){e=e||{};a=a.split(".");for(var g,f=0;1e?tc(d[0],d[1],d[2],d[3],d[4],c,a):function(b,g){var f=0,h;do h=tc(d[f++],d[f++],d[f++],d[f++],d[f++],c,a)(b,g),g=r,b=h;while(fa)for(b in g++,d)d.hasOwnProperty(b)&&!f.hasOwnProperty(b)&&(l--,delete d[b])}else d!==f&&(d=f,g++);return g},function(){b(f,d,c)})},$digest:function(){var c,e,f,g,m=this.$$asyncQueue,q=this.$$postDigestQueue,r,t,H=b,y,v=[],x,E,Z;h("$digest");do{t=!1;for(y=this;m.length;)try{Z=m.shift(),Z.scope.$eval(Z.expression)}catch(B){d(B)}do{if(g=y.$$watchers)for(r=g.length;r--;)try{(c= 99 | g[r])&&((e=c.get(y))!==(f=c.last)&&!(c.eq?Aa(e,f):"number"==typeof e&&"number"==typeof f&&isNaN(e)&&isNaN(f)))&&(t=!0,c.last=c.eq?ga(e):e,c.fn(e,f===k?e:f,y),5>H&&(x=4-H,v[x]||(v[x]=[]),E=I(c.exp)?"fn: "+(c.exp.name||c.exp.toString()):c.exp,E+="; newVal: "+oa(e)+"; oldVal: "+oa(f),v[x].push(E)))}catch(P){d(P)}if(!(g=y.$$childHead||y!==this&&y.$$nextSibling))for(;y!==this&&!(g=y.$$nextSibling);)y=y.$parent}while(y=g);if(t&&!H--)throw l.$$phase=null,a("infdig",b,oa(v));}while(t||m.length);for(l.$$phase= 100 | null;q.length;)try{q.shift()()}catch(N){d(N)}},$destroy:function(){if(l!=this&&!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail= 101 | null}},$eval:function(a,b){return e(a)(this,b)},$evalAsync:function(a){l.$$phase||l.$$asyncQueue.length||g.defer(function(){l.$$asyncQueue.length&&l.$digest()});this.$$asyncQueue.push({scope:this,expression:a})},$$postDigest:function(a){this.$$postDigestQueue.push(a)},$apply:function(a){try{return h("$apply"),this.$eval(a)}catch(b){d(b)}finally{l.$$phase=null;try{l.$digest()}catch(c){throw d(c),c;}}},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);return function(){c[bb(c, 102 | b)]=null}},$emit:function(a,b){var c=[],e,f=this,g=!1,h={name:a,targetScope:f,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=[h].concat(ta.call(arguments,1)),m,l;do{e=f.$$listeners[a]||c;h.currentScope=f;m=0;for(l=e.length;mc.msieDocumentMode)throw ra("iequirks");var e=ga(fa);e.isEnabled=function(){return b};e.trustAs=d.trustAs;e.getTrusted=d.getTrusted;e.valueOf=d.valueOf;b||(e.trustAs=e.getTrusted=function(a,b){return b},e.valueOf=za);e.parseAs=function(b,c){var d=a(c);return d.literal&&d.constant?d:function(a,c){return e.getTrusted(b,d(a,c))}};var g=e.parseAs, 109 | f=e.getTrusted,h=e.trustAs;q(fa,function(a,b){var c=t(b);e[Pa("parse_as_"+c)]=function(b){return g(a,b)};e[Pa("get_trusted_"+c)]=function(b){return f(a,b)};e[Pa("trust_as_"+c)]=function(b){return h(a,b)}});return e}]}function Cd(){this.$get=["$window","$document",function(b,a){var c={},d=S((/android (\d+)/.exec(t((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),g=a[0]||{},f=g.documentMode,h,m=/^(Moz|webkit|O|ms)(?=[A-Z])/,k=g.body&&g.body.style,l=!1,n=!1;if(k){for(var p in k)if(l= 110 | m.exec(p)){h=l[0];h=h.substr(0,1).toUpperCase()+h.substr(1);break}h||(h="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||h+"Transition"in k);n=!!("animation"in k||h+"Animation"in k);!d||l&&n||(l=w(g.body.style.webkitTransition),n=w(g.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hashchange:"onhashchange"in b&&(!f||7b;b=Math.abs(b);var f=b+"",h="",m=[],k=!1;if(-1!==f.indexOf("e")){var l=f.match(/([\d\.]+)e(-?)(\d+)/);l&&"-"==l[2]&&l[3]>e+1?f="0":(h=f,k=!0)}if(k)0b)&&(h=b.toFixed(e));else{f=(f.split(Ec)[1]||"").length;C(e)&&(e=Math.min(Math.max(a.minFrac,f),a.maxFrac)); 117 | f=Math.pow(10,e);b=Math.round(b*f)/f;b=(""+b).split(Ec);f=b[0];b=b[1]||"";var l=0,n=a.lgSize,p=a.gSize;if(f.length>=n+p)for(l=f.length-n,k=0;kb&&(d="-",b=-b);for(b=""+b;b.length-c)e+=c;0===e&&-12==c&&(e=12);return Lb(e,a,d)}}function jb(b,a){return function(c,d){var e=c["get"+b](),g=Ha(a?"SHORT"+b:b);return d[g][e]}}function Ac(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var g=0,f=0,h=b[8]?a.setUTCFullYear:a.setFullYear,m=b[8]?a.setUTCHours:a.setHours;b[9]&&(g=S(b[9]+b[10]),f=S(b[9]+b[11]));h.call(a,S(b[1]),S(b[2])-1,S(b[3]));g=S(b[4]||0)-g;f=S(b[5]||0)-f;h=S(b[6]||0);b=Math.round(1E3* 119 | parseFloat("0."+(b[7]||0)));m.call(a,g,f,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e){var g="",f=[],h,m;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;w(c)&&(c=Kd.test(c)?S(c):a(c));qb(c)&&(c=new Date(c));if(!Ka(c))return c;for(;e;)(m=Ld.exec(e))?(f=f.concat(ta.call(m,1)),e=f.pop()):(f.push(e),e=null);q(f,function(a){h=Md[a];g+=h?h(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}} 120 | function Gd(){return function(b){return oa(b,!0)}}function Hd(){return function(b,a){if(!K(b)&&!w(b))return b;a=S(a);if(w(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0a||37<=a&&40>=a)||k()});if(e.hasEvent("paste"))a.on("paste cut",k)}a.on("change",h);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)};var l=c.ngPattern, 125 | n=function(a,b){if(d.$isEmpty(b)||a.test(b))return d.$setValidity("pattern",!0),b;d.$setValidity("pattern",!1);return r};l&&((e=l.match(/^\/(.*)\/([gim]*)$/))?(l=RegExp(e[1],e[2]),e=function(a){return n(l,a)}):e=function(c){var d=b.$eval(l);if(!d||!d.test)throw A("ngPattern")("noregexp",l,d,ha(a));return n(d,c)},d.$formatters.push(e),d.$parsers.push(e));if(c.ngMinlength){var p=S(c.ngMinlength);e=function(a){if(!d.$isEmpty(a)&&a.lengths)return d.$setValidity("maxlength",!1),r;d.$setValidity("maxlength",!0);return a};d.$parsers.push(e);d.$formatters.push(e)}}function Mb(b,a){b="ngClass"+b;return function(){return{restrict:"AC",link:function(c,d,e){function g(b){if(!0===a||c.$index%2===a){var d=f(b||"");h?Aa(b,h)||e.$updateClass(d,f(h)):e.$addClass(d)}h=ga(b)}function f(a){if(K(a))return a.join(" "); 127 | if(V(a)){var b=[];q(a,function(a,c){a&&b.push(c)});return b.join(" ")}return a}var h;c.$watch(e[b],g,!0);e.$observe("class",function(a){g(c.$eval(e[b]))});"ngClass"!==b&&c.$watch("$index",function(d,g){var h=d&1;if(h!==g&1){var n=f(c.$eval(e[b]));h===a?e.$addClass(n):e.$removeClass(n)}})}}}}var t=function(b){return w(b)?b.toLowerCase():b},Ha=function(b){return w(b)?b.toUpperCase():b},M,x,Ba,ta=[].slice,Nd=[].push,$a=Object.prototype.toString,Ma=A("ng"),cb=X.angular||(X.angular={}),Ua,Ea,ja=["0","0", 128 | "0"];M=S((/msie (\d+)/.exec(t(navigator.userAgent))||[])[1]);isNaN(M)&&(M=S((/trident\/.*; rv:(\d+)/.exec(t(navigator.userAgent))||[])[1]));v.$inject=[];za.$inject=[];var $=function(){return String.prototype.trim?function(b){return w(b)?b.trim():b}:function(b){return w(b)?b.replace(/^\s\s*/,"").replace(/\s\s*$/,""):b}}();Ea=9>M?function(b){b=b.nodeName?b:b[0];return b.scopeName&&"HTML"!=b.scopeName?Ha(b.scopeName+":"+b.nodeName):b.nodeName}:function(b){return b.nodeName?b.nodeName:b[0].nodeName}; 129 | var Sc=/[A-Z]/g,Od={full:"1.2.3",major:1,minor:2,dot:3,codeName:"unicorn-zapper"},Ra=L.cache={},eb=L.expando="ng-"+(new Date).getTime(),Wc=1,Gc=X.document.addEventListener?function(b,a,c){b.addEventListener(a,c,!1)}:function(b,a,c){b.attachEvent("on"+a,c)},Ab=X.document.removeEventListener?function(b,a,c){b.removeEventListener(a,c,!1)}:function(b,a,c){b.detachEvent("on"+a,c)},Uc=/([\:\-\_]+(.))/g,Vc=/^moz([A-Z])/,xb=A("jqLite"),Da=L.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1; 130 | "complete"===O.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),L(X).on("load",a))},toString:function(){var b=[];q(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?x(this[b]):x(this[this.length+b])},length:0,push:Nd,sort:[].sort,splice:[].splice},gb={};q("multiple selected checked disabled readOnly required open".split(" "),function(b){gb[t(b)]=b});var dc={};q("input select option textarea button form details".split(" "),function(b){dc[Ha(b)]=!0});q({data:ac, 131 | inheritedData:fb,scope:function(b){return x(b).data("$scope")||fb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return x(b).data("$isolateScope")||x(b).data("$isolateScopeNoTemplate")},controller:bc,injector:function(b){return fb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Bb,css:function(b,a,c){a=Pa(a);if(B(c))b.style[a]=c;else{var d;8>=M&&(d=b.currentStyle&&b.currentStyle[a],""===d&&(d="auto"));d=d||b.style[a];8>=M&&(d=""===d?r:d);return d}},attr:function(b, 132 | a,c){var d=t(a);if(gb[d])if(B(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:r;else if(B(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?r:b},prop:function(b,a,c){if(B(c))b[a]=c;else return b[a]},text:function(){function b(b,d){var e=a[b.nodeType];if(C(d))return e?b[e]:"";b[e]=d}var a=[];9>M?(a[1]="innerText",a[3]="nodeValue"):a[1]=a[3]="textContent";b.$dv="";return b}(),val:function(b, 133 | a){if(C(a)){if("SELECT"===Ea(b)&&b.multiple){var c=[];q(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(C(a))return b.innerHTML;for(var c=0,d=b.childNodes;c":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"&":function(a,c,d,e){return d(a,c)&e(a,c)},"|":function(a,c,d,e){return e(a,c)(a,c,d(a,c))},"!":function(a,c,d){return!d(a,c)}},Sd={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},Kb=function(a){this.options=a};Kb.prototype={constructor:Kb,lex:function(a){this.text=a; 145 | this.index=0;this.ch=r;this.lastCh=":";this.tokens=[];var c;for(a=[];this.index=a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"=== 148 | a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=B(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw xa("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index","<=",">="))a=this.binaryFn(a,c.fn,this.relational());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+", 159 | "-");)a=this.binaryFn(a,c.fn,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.fn,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(Ya.ZERO,a.fn,this.unary()):(a=this.expect("!"))?this.unaryFn(a.fn,this.unary()):this.primary()},fieldAccess:function(a){var c=this,d=this.expect().text,e=uc(d,this.options,this.text);return F(function(c,d,h){return e(h|| 160 | a(c,d),d)},{assign:function(e,f,h){return ib(a(e,h),d,f,c.text,c.options)}})},objectIndex:function(a){var c=this,d=this.expression();this.consume("]");return F(function(e,g){var f=a(e,g),h=d(e,g),m;if(!f)return r;(f=Xa(f[h],c.text))&&(f.then&&c.options.unwrapPromises)&&(m=f,"$$v"in f||(m.$$v=r,m.then(function(a){m.$$v=a})),f=f.$$v);return f},{assign:function(e,g,f){var h=d(e,f);return Xa(a(e,f),c.text)[h]=g}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression()); 161 | while(this.expect(","))}this.consume(")");var e=this;return function(g,f){for(var h=[],m=c?c(g,f):g,k=0;ka.getHours()? 164 | c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Lb(Math[0=M&&(c.href||c.name||c.$set("href",""),a.append(O.createComment("IE fix")));return function(a,c){c.on("click",function(a){c.attr("href")||a.preventDefault()})}}}), 165 | Nb={};q(gb,function(a,c){if("multiple"!=a){var d=ma("ng-"+c);Nb[d]=function(){return{priority:100,compile:function(){return function(a,g,f){a.$watch(f[d],function(a){f.$set(c,!!a)})}}}}}});q(["src","srcset","href"],function(a){var c=ma("ng-"+a);Nb[c]=function(){return{priority:99,link:function(d,e,g){g.$observe(c,function(c){c&&(g.$set(a,c),M&&e.prop(a,g[a]))})}}}});var mb={$addControl:v,$removeControl:v,$setValidity:v,$setDirty:v,$setPristine:v};Fc.$inject=["$element","$attrs","$scope"];var Hc=function(a){return["$timeout", 166 | function(c){return{name:"form",restrict:a?"EAC":"E",controller:Fc,compile:function(){return{pre:function(a,e,g,f){if(!g.action){var h=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1};Gc(e[0],"submit",h);e.on("$destroy",function(){c(function(){Ab(e[0],"submit",h)},0,!1)})}var m=e.parent().controller("form"),k=g.name||g.ngForm;k&&ib(a,k,f,k);if(m)e.on("$destroy",function(){m.$removeControl(f);k&&ib(a,k,r,k);F(f,mb)})}}}}}]},Ud=Hc(),Vd=Hc(!0),Wd=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/, 167 | Xd=/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$/,Yd=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,Ic={text:ob,number:function(a,c,d,e,g,f){ob(a,c,d,e,g,f);e.$parsers.push(function(a){var c=e.$isEmpty(a);if(c||Yd.test(a))return e.$setValidity("number",!0),""===a?null:c?a:parseFloat(a);e.$setValidity("number",!1);return r});e.$formatters.push(function(a){return e.$isEmpty(a)?"":""+a});d.min&&(a=function(a){var c=parseFloat(d.min);if(!e.$isEmpty(a)&&ac)return e.$setValidity("max",!1),r;e.$setValidity("max",!0);return a},e.$parsers.push(a),e.$formatters.push(a));e.$formatters.push(function(a){if(e.$isEmpty(a)||qb(a))return e.$setValidity("number",!0),a;e.$setValidity("number",!1);return r})},url:function(a,c,d,e,g,f){ob(a,c,d,e,g,f);a=function(a){if(e.$isEmpty(a)||Wd.test(a))return e.$setValidity("url",!0),a;e.$setValidity("url", 169 | !1);return r};e.$formatters.push(a);e.$parsers.push(a)},email:function(a,c,d,e,g,f){ob(a,c,d,e,g,f);a=function(a){if(e.$isEmpty(a)||Xd.test(a))return e.$setValidity("email",!0),a;e.$setValidity("email",!1);return r};e.$formatters.push(a);e.$parsers.push(a)},radio:function(a,c,d,e){C(d.name)&&c.attr("name",Za());c.on("click",function(){c[0].checked&&a.$apply(function(){e.$setViewValue(d.value)})});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a, 170 | c,d,e){var g=d.ngTrueValue,f=d.ngFalseValue;w(g)||(g=!0);w(f)||(f=!1);c.on("click",function(){a.$apply(function(){e.$setViewValue(c[0].checked)})});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return a!==g};e.$formatters.push(function(a){return a===g});e.$parsers.push(function(a){return a?g:f})},hidden:v,button:v,submit:v,reset:v},Jc=["$browser","$sniffer",function(a,c){return{restrict:"E",require:"?ngModel",link:function(d,e,g,f){f&&(Ic[t(g.type)]||Ic.text)(d,e,g,f,c,a)}}}], 171 | lb="ng-valid",kb="ng-invalid",Ia="ng-pristine",nb="ng-dirty",Zd=["$scope","$exceptionHandler","$attrs","$element","$parse",function(a,c,d,e,g){function f(a,c){c=c?"-"+db(c,"-"):"";e.removeClass((a?kb:lb)+c).addClass((a?lb:kb)+c)}this.$modelValue=this.$viewValue=Number.NaN;this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$name=d.name;var h=g(d.ngModel),m=h.assign;if(!m)throw A("ngModel")("nonassign",d.ngModel,ha(e)); 172 | this.$render=v;this.$isEmpty=function(a){return C(a)||""===a||null===a||a!==a};var k=e.inheritedData("$formController")||mb,l=0,n=this.$error={};e.addClass(Ia);f(!0);this.$setValidity=function(a,c){n[a]!==!c&&(c?(n[a]&&l--,l||(f(!0),this.$valid=!0,this.$invalid=!1)):(f(!1),this.$invalid=!0,this.$valid=!1,l++),n[a]=!c,f(c,a),k.$setValidity(a,c,this))};this.$setPristine=function(){this.$dirty=!1;this.$pristine=!0;e.removeClass(nb).addClass(Ia)};this.$setViewValue=function(d){this.$viewValue=d;this.$pristine&& 173 | (this.$dirty=!0,this.$pristine=!1,e.removeClass(Ia).addClass(nb),k.$setDirty());q(this.$parsers,function(a){d=a(d)});this.$modelValue!==d&&(this.$modelValue=d,m(a,d),q(this.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}}))};var p=this;a.$watch(function(){var c=h(a);if(p.$modelValue!==c){var d=p.$formatters,e=d.length;for(p.$modelValue=c;e--;)c=d[e](c);p.$viewValue!==c&&(p.$viewValue=c,p.$render())}})}],$d=function(){return{require:["ngModel","^?form"],controller:Zd,link:function(a,c,d,e){var g= 174 | e[0],f=e[1]||mb;f.$addControl(g);a.$on("$destroy",function(){f.$removeControl(g)})}}},ae=ba({require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),Kc=function(){return{require:"?ngModel",link:function(a,c,d,e){if(e){d.required=!0;var g=function(a){if(d.required&&e.$isEmpty(a))e.$setValidity("required",!1);else return e.$setValidity("required",!0),a};e.$formatters.push(g);e.$parsers.unshift(g);d.$observe("required",function(){g(e.$viewValue)})}}}}, 175 | be=function(){return{require:"ngModel",link:function(a,c,d,e){var g=(a=/\/(.*)\//.exec(d.ngList))&&RegExp(a[1])||d.ngList||",";e.$parsers.push(function(a){if(!C(a)){var c=[];a&&q(a.split(g),function(a){a&&c.push($(a))});return c}});e.$formatters.push(function(a){return K(a)?a.join(", "):r});e.$isEmpty=function(a){return!a||!a.length}}}},ce=/^(true|false|\d+)$/,de=function(){return{priority:100,compile:function(a,c){return ce.test(c.ngValue)?function(a,c,g){g.$set("value",a.$eval(g.ngValue))}:function(a, 176 | c,g){a.$watch(g.ngValue,function(a){g.$set("value",a)})}}}},ee=sa(function(a,c,d){c.addClass("ng-binding").data("$binding",d.ngBind);a.$watch(d.ngBind,function(a){c.text(a==r?"":a)})}),fe=["$interpolate",function(a){return function(c,d,e){c=a(d.attr(e.$attr.ngBindTemplate));d.addClass("ng-binding").data("$binding",c);e.$observe("ngBindTemplate",function(a){d.text(a)})}}],ge=["$sce","$parse",function(a,c){return function(d,e,g){e.addClass("ng-binding").data("$binding",g.ngBindHtml);var f=c(g.ngBindHtml); 177 | d.$watch(function(){return(f(d)||"").toString()},function(c){e.html(a.getTrustedHtml(f(d))||"")})}}],he=Mb("",!0),ie=Mb("Odd",0),je=Mb("Even",1),ke=sa({compile:function(a,c){c.$set("ngCloak",r);a.removeClass("ng-cloak")}}),le=[function(){return{scope:!0,controller:"@",priority:500}}],Lc={};q("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ma("ng-"+a);Lc[c]=["$parse",function(d){return{compile:function(e, 178 | g){var f=d(g[c]);return function(c,d,e){d.on(t(a),function(a){c.$apply(function(){f(c,{$event:a})})})}}}}]});var me=["$animate",function(a){return{transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,g,f){var h,m;c.$watch(e.ngIf,function(g){Na(g)?m||(m=c.$new(),f(m,function(c){h={startNode:c[0],endNode:c[c.length++]=O.createComment(" end ngIf: "+e.ngIf+" ")};a.enter(c,d.parent(),d)})):(m&&(m.$destroy(),m=null),h&&(a.leave(vb(h)),h=null))})}}}],ne=["$http","$templateCache", 179 | "$anchorScroll","$compile","$animate","$sce",function(a,c,d,e,g,f){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",compile:function(h,m){var k=m.ngInclude||m.src,l=m.onload||"",n=m.autoscroll;return function(h,m,q,r,t){var z=0,x,H,y=function(){x&&(x.$destroy(),x=null);H&&(g.leave(H),H=null)};h.$watch(f.parseAsResourceUrl(k),function(f){var k=function(){!B(n)||n&&!h.$eval(n)||d()},q=++z;f?(a.get(f,{cache:c}).success(function(a){if(q===z){var c=h.$new(),d=t(c,v);y();x=c;H=d;H.html(a); 180 | g.enter(H,null,m,k);e(H.contents())(x);x.$emit("$includeContentLoaded");h.$eval(l)}}).error(function(){q===z&&y()}),h.$emit("$includeContentRequested")):y()})}}}}],oe=sa({compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),pe=sa({terminal:!0,priority:1E3}),qe=["$locale","$interpolate",function(a,c){var d=/{}/g;return{restrict:"EA",link:function(e,g,f){var h=f.count,m=f.$attr.when&&g.attr(f.$attr.when),k=f.offset||0,l=e.$eval(m)||{},n={},p=c.startSymbol(),s=c.endSymbol(),r=/^when(Minus)?(.+)$/; 181 | q(f,function(a,c){r.test(c)&&(l[t(c.replace("when","").replace("Minus","-"))]=g.attr(f.$attr[c]))});q(l,function(a,e){n[e]=c(a.replace(d,p+h+"-"+k+s))});e.$watch(function(){var c=parseFloat(e.$eval(h));if(isNaN(c))return"";c in l||(c=a.pluralCat(c-k));return n[c](e,g,!0)},function(a){g.text(a)})}}}],re=["$parse","$animate",function(a,c){var d=A("ngRepeat");return{transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,link:function(e,g,f,h,m){var k=f.ngRepeat,l=k.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), 182 | n,p,s,r,u,t,v={$id:Ca};if(!l)throw d("iexp",k);f=l[1];h=l[2];(l=l[4])?(n=a(l),p=function(a,c,d){t&&(v[t]=a);v[u]=c;v.$index=d;return n(e,v)}):(s=function(a,c){return Ca(c)},r=function(a){return a});l=f.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);if(!l)throw d("iidexp",f);u=l[3]||l[1];t=l[2];var B={};e.$watchCollection(h,function(a){var f,h,l=g[0],n,v={},z,P,N,T,C,w,F=[];if(pb(a))C=a,n=p||s;else{n=p||r;C=[];for(N in a)a.hasOwnProperty(N)&&"$"!=N.charAt(0)&&C.push(N);C.sort()}z=C.length; 183 | h=F.length=C.length;for(f=0;fJ;)u.pop().element.remove()}for(;y.length>A;)y.pop()[0].element.remove()}var k;if(!(k=t.match(d)))throw Ae("iexp",t,ha(f));var m=c(k[2]||k[1]),l=k[4]||k[6],n=k[5],p=c(k[3]||""),q=c(k[2]?k[1]:l),s=c(k[7]),x=k[8]?c(k[8]):null,y=[[{element:f,label:""}]];w&&(a(w)(e),w.removeClass("ng-scope"),w.remove());f.html("");f.on("change", 194 | function(){e.$apply(function(){var a,c=s(e)||[],d={},h,k,m,p,t,u,w;if(v)for(k=[],p=0,u=y.length;p@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-start{border-spacing:1px 1px;-ms-zoom:1.0001;}.ng-animate-active{border-spacing:0px 0px;-ms-zoom:1;}'); 201 | //# sourceMappingURL=angular.min.js.map 202 | --------------------------------------------------------------------------------