├── .editorconfig
├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gruntfile.js
├── LICENSE
├── OLD-README.md
├── README.md
├── UPGRADING.md
├── benchmark
└── api-key-encryption.js
├── collection_each_example.js
├── docs-dev.sh
├── docs
├── JSDOC.md
├── develop.sh
├── jsdoc.json
└── template
│ ├── jsdoc.conf.json
│ ├── publish.js
│ ├── static
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ ├── img
│ │ ├── glyphicons-halflings-white.png
│ │ └── glyphicons-halflings.png
│ ├── scripts
│ │ ├── docstrap.lib.js
│ │ ├── fulltext-search-ui.js
│ │ ├── fulltext-search.js
│ │ ├── lunr.min.js
│ │ ├── prettify
│ │ │ ├── Apache-License-2.0.txt
│ │ │ ├── jquery.min.js
│ │ │ ├── lang-css.js
│ │ │ └── prettify.js
│ │ ├── sunlight.js
│ │ └── toc.js
│ └── styles
│ │ ├── site.cosmo.css
│ │ ├── sunlight.dark.css
│ │ └── sunlight.default.css
│ └── tmpl
│ ├── augments.tmpl
│ ├── container.tmpl
│ ├── details.tmpl
│ ├── example.tmpl
│ ├── examples.tmpl
│ ├── exceptions.tmpl
│ ├── fires.tmpl
│ ├── layout.tmpl
│ ├── mainpage.tmpl
│ ├── members.tmpl
│ ├── method.tmpl
│ ├── params.tmpl
│ ├── properties.tmpl
│ ├── quicksearch.tmpl
│ ├── returns.tmpl
│ ├── sections.tmpl
│ ├── source.tmpl
│ ├── tutorial.tmpl
│ └── type.tmpl
├── lib
├── Client.js
├── authc
│ ├── ApiKey.js
│ ├── ApiKeyEncryptedOptions.js
│ ├── ApiKeyLoader.js
│ ├── AssertionAuthenticationResult.js
│ ├── AuthRequestParser.js
│ ├── BasicApiAuthenticator.js
│ ├── BasicRequestAuthenticator.js
│ ├── ClientCredentialGrantAuthenticator.js
│ ├── OAuthBasicExchangeAuthenticator.js
│ ├── OauthAccessTokenAuthenticator.js
│ ├── RequestAuthenticator.js
│ ├── Sauthc1RequestAuthenticator.js
│ ├── StormpathAssertionAuthenticator.js
│ └── index.js
├── cache
│ ├── Cache.js
│ ├── CacheEntry.js
│ ├── CacheHandler.js
│ ├── CacheManager.js
│ ├── CacheStats.js
│ ├── DisabledCache.js
│ ├── MemcachedStore.js
│ ├── MemoryStore.js
│ ├── RedisStore.js
│ └── index.js
├── config.yml
├── configLoader.js
├── ds
│ ├── DataStore.js
│ ├── NonceStore.js
│ └── RequestExecutor.js
├── error
│ ├── ApiAuthRequestError.js
│ ├── ResourceError.js
│ ├── invalid-href.js
│ └── messages.js
├── index.js
├── jwt
│ ├── jwt-authentication-result.js
│ └── jwt-authenticator.js
├── oauth
│ ├── authenticator.js
│ ├── client-credentials.js
│ ├── id-site-grant.js
│ ├── password-grant.js
│ ├── refresh-grant.js
│ ├── scope-factory-authenticator.js
│ ├── stormpath-access-token-authentication-result.js
│ ├── stormpath-access-token-authenticator.js
│ ├── stormpath-social.js
│ └── stormpath-token.js
├── proxy
│ └── ObjectCallProxy.js
├── resource
│ ├── AccessToken.js
│ ├── Account.js
│ ├── AccountCreationPolicy.js
│ ├── AccountLink.js
│ ├── AccountLinkingPolicy.js
│ ├── AccountStoreMapping.js
│ ├── ApiKey.js
│ ├── Application.js
│ ├── ApplicationAccountStoreMapping.js
│ ├── AuthenticationResult.js
│ ├── Challenge.js
│ ├── CollectionResource.js
│ ├── CustomData.js
│ ├── Directory.js
│ ├── DirectoryChildResource.js
│ ├── Factor.js
│ ├── FactorInstantiator.js
│ ├── Field.js
│ ├── GoogleAuthenticatorFactor.js
│ ├── Group.js
│ ├── GroupMembership.js
│ ├── IdSiteModel.js
│ ├── InstanceResource.js
│ ├── OAuthPolicy.js
│ ├── Organization.js
│ ├── OrganizationAccountStoreMapping.js
│ ├── PasswordPolicy.js
│ ├── PasswordResetToken.js
│ ├── Phone.js
│ ├── Provider.js
│ ├── ProviderData.js
│ ├── RefreshToken.js
│ ├── Resource.js
│ ├── ResourceFactory.js
│ ├── SamlAttributeStatementMappingRules.js
│ ├── SamlPolicy.js
│ ├── SamlProvider.js
│ ├── SamlServiceProvider.js
│ ├── SamlServiceProviderMetadata.js
│ ├── Schema.js
│ ├── SmsFactor.js
│ ├── SmtpServer.js
│ ├── Strength.js
│ ├── Tenant.js
│ └── mixins
│ │ └── SaveableMixin.js
├── saml
│ └── SamlIdpUrlBuilder.js
├── stormpath.js
├── underscore.js
└── utils.js
├── package.json
├── quickstart.js
└── test
├── apikey_test.js
├── common.js
├── fixtures
├── account-token.js
└── apiKey.properties
├── it
├── access-token-authenticator.js
├── account_it.js
├── api_auth_it.js
├── api_keys_it.js
├── application_it.js
├── assertion_authentication_result_it.js
├── client_credential_auth_it.js
├── client_it.js
├── datastore_it.js
├── directory_it.js
├── group_it.js
├── helpers.js
├── jwt_authenticator_it.js
├── oauth_authenticator_it.js
├── oauth_client_credentials_it.js
├── oauth_id_site_token_grant_it.js
├── oauth_password_grant_it.js
├── oauth_refresh_grant_it.js
├── oauth_stormpath_socal_it.js
├── oauth_stormpath_token_it.js
├── organization_it.js
├── password_policy_it.js
├── saml_idp_url_builder_it.js
├── stormpath_assertion_authenticator_it.js
└── tenant_it.js
├── live
├── sp.cache.memcachedStore_live.js
└── sp.cache.redisStore_live.js
├── sp.auth.unit_test.js
├── sp.authc.apiKeyLoader_test.js
├── sp.authc.apiKey_test.js
├── sp.authc.authRequestParser_test.js
├── sp.authc.requestAuthenticator_test.js
├── sp.cache.cacheHandler_test.js
├── sp.cache.cache_test.js
├── sp.cache.disabledCache_test.js
├── sp.cache.entry_test.js
├── sp.cache.manager_test.js
├── sp.cache.memoryStore_test.js
├── sp.cache.stats_test.js
├── sp.client_test.js
├── sp.config.configLoader_test.js
├── sp.ds.datastore_test.js
├── sp.ds.requestExecutor_test.js
├── sp.error.resourceError_test.js
├── sp.proxy.objectcallproxy_test.js
├── sp.resource.accountLink_test.js
├── sp.resource.accountLinkingPolicy_test.js
├── sp.resource.accountStoreMapping_test.js
├── sp.resource.account_test.js
├── sp.resource.apikey_test.js
├── sp.resource.application_test.js
├── sp.resource.authenticationResult_test.js
├── sp.resource.challenge_test.js
├── sp.resource.collectionResource_test.js
├── sp.resource.customData_test.js
├── sp.resource.directoryChildResource_test.js
├── sp.resource.directory_test.js
├── sp.resource.factorInstantiator_test.js
├── sp.resource.factor_test.js
├── sp.resource.field_test.js
├── sp.resource.googleAuthenticatorFactor_test.js
├── sp.resource.groupMembership_test.js
├── sp.resource.group_test.js
├── sp.resource.instanceResource_test.js
├── sp.resource.organization_test.js
├── sp.resource.phone_test.js
├── sp.resource.resourceFactory_test.js
├── sp.resource.resource_test.js
├── sp.resource.schema_test.js
├── sp.resource.smsFactor_test.js
├── sp.resource.tenant_test.js
└── sp.utils_test.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Indentation override for all JS under lib directory
7 | [**.js]
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | indent_style = space
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_size = 2
14 |
15 | [**.yml]
16 | indent_style = space
17 | indent_size = 2
18 | end_of_line = lf
19 | charset = utf-8
20 | trim_trailing_whitespace = true
21 | insert_final_newline = true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /coverage
3 | apidocs
4 | npm-debug.log
5 | *.ipr
6 | *.iws
7 | *.iml
8 | .idea
9 | .DS_Store
10 | .coveralls.yml
11 | .env
12 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "curly": true,
3 | "eqeqeq": true,
4 | "immed": true,
5 | "latedef": true,
6 | "newcap": true,
7 | "noarg": true,
8 | "sub": true,
9 | "undef": true,
10 | "unused": true,
11 | "boss": true,
12 | "eqnull": true,
13 | "node": true,
14 | "globals": {
15 | /* MOCHA */
16 | "describe": false,
17 | "it": false,
18 | "before": false,
19 | "beforeEach": false,
20 | "after": false,
21 | "afterEach": false
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .coveralls.yml
2 | .env
3 | apidocs
4 | docs
5 | samples
6 | test
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.10'
4 | - '0.12'
5 | - 'iojs'
6 | - '4'
7 | - '6'
8 | sudo: false
9 | script: travis_retry npm test
10 | env:
11 | global:
12 | - secure: axSfLtwNV9cKG+Y7UslwPddxyPbvbEwbyWDUt9ONRkFIpNAbtuRvjSSl2tAmJ9m9vFDV0I63shYaCkwz6gFiJDGRlYjWHqgBknm8jOBLYIk68mrSHzQZLdoAqoEhAe+UCJSvoQGkLeuPuVw5/lVWZ6Uv6dzSsU/8dVlsp23G9Hc=
13 | - secure: RVyH3nRU3yjeVUCMkOYy7KuRG0bFHMANbQsEbxuZ2ad/KMYNNDJ/AfyO3Q5ojAj/uX59NLYyzyFODhXikEaFsIvgCHbGLkgBYSNIVUIdaS509KMOUwcN6ZDDUpVS21E2rEJwY7/BGenJKZJ1N3NLf6yqciS2KYoo7TVdnTaNUh8=
14 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guide
2 |
3 | We love pull requests!
4 |
5 | Here are a few things you'll need to know if you want to make a contribution to
6 | this library.
7 |
8 | ### Submitting Pull Requests
9 |
10 | Pull requests are welcome, and will be reviewed as soon as possible. Please
11 | ensure that the tests are passing and that new features have test coverage. When
12 | you submit the PR the tests will fail on Travis, even if they are working locally.
13 | This is because we use encrypted environment variables on Travis, and this will
14 | fail for PRs from forks. This is okay, we will pull down your branch and run
15 | the tests locally for confirmation.
16 |
17 | ### Documentation
18 |
19 | This library uses JsDoc for documentation. To build the docs:
20 |
21 | ```
22 | npm run docs
23 | ```
24 |
25 | The output will be placed in `./apidocs`. If you are going to do a lot of work
26 | on the documentation, I suggest the development script, it will rebuild the
27 | files when you make changes, and open a web server with the documentation:
28 |
29 | ```
30 | ./docs/develop.sh
31 | ```
32 |
33 | If you need to modify the theme or template, you can find that in `docs/template`.
34 | This template was cloned from the [Docstrap][] project.
35 |
36 | [Docstrap]: https://github.com/docstrap/docstrap
37 |
38 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function (grunt) {
4 |
5 | // Show elapsed time at the end
6 | require('time-grunt')(grunt);
7 | // Load all grunt tasks
8 | require('load-grunt-tasks')(grunt);
9 |
10 | // Project configuration.
11 | grunt.initConfig({
12 | mochaTest: {
13 | test: {
14 | src: ['test/**/*_test.js'],
15 | options: {
16 | timeout: 30000
17 | }
18 |
19 | },
20 | live: {
21 | src: ['test/**/*_live.js']
22 | }
23 | },
24 | mocha_istanbul: {
25 | test: {
26 | src: ['test/it/*_it.js', 'test/**/*_test.js'],
27 | options: {
28 | coverage: true,
29 | require: ['test/common.js'],
30 | timeout: 30000
31 | }
32 | },
33 | coverage: {
34 | src: 'test', // the folder, not the files,
35 | options: {
36 | mask: '**/*_test.js',
37 | require: ['test/common.js'],
38 | timeout: 30000
39 | }
40 | },
41 | it: {
42 | src: 'test', // the folder, not the files,
43 | options: {
44 | mask: '**/*_it.js',
45 | require: ['test/common.js'],
46 | timeout: 30000
47 | }
48 | }
49 | },
50 | jshint: {
51 | options: {
52 | jshintrc: '.jshintrc',
53 | reporter: require('jshint-stylish')
54 | },
55 | gruntfile: {
56 | src: 'Gruntfile.js'
57 | },
58 | lib: {
59 | src: ['lib/**/*.js']
60 | },
61 | test: {
62 | src: ['test/**/*.js']
63 | }
64 | },
65 | watch: {
66 | gruntfile: {
67 | files: '<%= jshint.gruntfile.src %>',
68 | tasks: ['jshint:gruntfile']
69 | },
70 | lib: {
71 | files: '<%= jshint.lib.src %>',
72 | tasks: ['jshint:lib', 'mochaTest']
73 | },
74 | test: {
75 | files: '<%= jshint.test.src %>',
76 | tasks: ['jshint:test', 'mochaTest']
77 | }
78 | }
79 | });
80 |
81 | grunt.loadNpmTasks('grunt-contrib-jshint');
82 | grunt.loadNpmTasks('grunt-contrib-watch');
83 | grunt.loadNpmTasks('grunt-mocha-istanbul');
84 | grunt.loadNpmTasks('grunt-mocha-test');
85 |
86 | // Default task.
87 | grunt.registerTask('test', ['mochaTest:test']);
88 | grunt.registerTask('it', ['jshint','mocha_istanbul:it']);
89 | grunt.registerTask('live', ['mochaTest:live']);
90 | grunt.registerTask('coverage', ['mocha_istanbul:coverage']);
91 | grunt.registerTask('default', ['jshint', 'mocha_istanbul:test']);
92 |
93 | // Once our coverage reports have been generated, fire off coverage reports to
94 | // coveralls.io so our coverage is made public.
95 | grunt.event.on('coverage', function(lcov, done) {
96 | require('coveralls').handleInput(lcov, function(err) {
97 | done(err);
98 | });
99 | });
100 | };
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stormpath is Joining Okta
2 |
3 | We are incredibly excited to announce that [Stormpath is joining forces with Okta](https://stormpath.com/blog/stormpaths-new-path?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement). Please visit [the Migration FAQs](https://stormpath.com/oktaplusstormpath?utm_source=github&utm_medium=readme&utm-campaign=okta-announcement) for a detailed look at what this means for Stormpath users.
4 |
5 | We're available to answer all questions at [support@stormpath.com](mailto:support@stormpath.com).
6 |
7 | ## What does this mean for developers who are using this library?
8 |
9 | This library is not being patched to work with Okta. If you are using this library, you should consider using the new [Okta Node SDK][] or manually integrating with an HTTP client. Please see the [Okta API reference][] for more information about the API.
10 |
11 | If you are using [Express-Stormpath][], that library is depending on the [okta branch] in this library. That branch is being maintained for [Express-Stormpath][] only. Using this branch directly is not supported.
12 |
13 | ## README
14 |
15 | If you are actively using this library, you can find the readme in [OLD-README.md](OLD-README.md).
16 | It is not possible to register for new Stormpath tenants at this time, so you must
17 | already have a Stormpath tenant if you wish to use this library during the migration
18 | period.
19 |
20 | [Express-Stormpath]: https://github.com/stormpath/express-stormpath
21 | [okta branch]: https://github.com/stormpath/stormpath-sdk-node/tree/okta
22 | [Okta API reference]: https://okta.github.io/docs/api/resources/apps.html
23 | [Okta Node SDK]: https://github.com/okta/okta-sdk-nodejs
--------------------------------------------------------------------------------
/UPGRADING.md:
--------------------------------------------------------------------------------
1 | # Upgrade Guide
2 |
3 | ### Version 0.20.0 -> Version 0.20.1
4 |
5 | No changes needed
6 |
7 | ### Version 0.19.2 -> Version 0.20.0
8 |
9 | The authenticator class `JwtAuthenticator` has been deprecated, please use `StormpathAccessTokenAuthenticator` instead.
10 |
11 | ### Version 0.19.1 -> Version 0.19.2
12 |
13 | No changes needed
14 |
15 | ### Version 0.19.0 -> Version 0.19.1
16 |
17 | No changes needed
18 |
19 | ### Version 0.18.5 -> Version 0.19.0
20 |
21 | No changes needed
22 |
23 | ### Version 0.18.4 -> Version 0.18.5
24 |
25 | No changes needed
26 |
27 | ### Version 0.18.3 -> Version 0.18.4
28 |
29 | No changes needed
30 |
31 | ### Version 0.18.2 -> Version 0.18.3
32 |
33 | No changes needed
34 |
35 | ### Version 0.18.1 -> Version 0.18.2
36 |
37 | No changes needed
38 |
39 | ### Version 0.18.0 -> Version 0.18.1
40 |
41 | No changes needed
42 |
43 | ### Version 0.17.5 -> Version 0.18.0
44 |
45 | No changes needed
46 |
47 | ### Version 0.17.4 -> Version 0.17.5
48 |
49 | No changes needed
50 |
51 | ### Version 0.17.3 -> Version 0.17.4
52 |
53 | No changes needed
54 |
55 | ### Version 0.17.2 -> Version 0.17.3
56 |
57 | No changes needed
58 |
59 | ### Version 0.17.1 -> Version 0.17.2
60 |
61 | No changes needed
62 |
63 | ### Version 0.17.0 -> Version 0.17.1
64 |
65 | No changes needed
66 |
67 | ### Version 0.16.0 -> Version 0.17.0
68 |
69 | * `OAuthIdSiteTokenGrantAuthenticator` has been deprecated. Please use the
70 | new `OAuthStormpathTokenAuthenticator` instead.
71 |
72 | ### Version 0.15.5 -> Version 0.16.0
73 |
74 | No changes needed
75 |
76 | ### Version 0.15.4 -> Version 0.15.5
77 |
78 | No changes needed
79 |
80 | ### Version 0.15.3 -> Version 0.15.4
81 |
82 | No changes needed
83 |
84 | ### Version 0.15.2 -> Version 0.15.3
85 |
86 | No changes needed
87 |
88 | ### Version 0.15.1 -> Version 0.15.2
89 |
90 | No changes needed
91 |
92 | ### Version 0.15.0 -> Version 0.15.1
93 |
94 | No changes needed
95 |
96 | ### Version 0.14.0 -> Version 0.15.0
97 |
98 | If you were relying on this module to enrich your client configuration with
99 | a Stormpath application and default account store, you will need to move
100 | that strategy, `EnrichClientFromRemoteConfigStrategy()`, into your application's
101 | client configuration strategy list (it is no longer done by this library).
102 |
103 | ### Version 0.13.5 -> Version 0.14.0
104 |
105 | No changes needed
106 |
107 | ### Version 0.13.4 -> Version 0.13.5
108 |
109 | No changes needed
110 |
111 | ### Version 0.13.3 -> Version 0.13.4
112 |
113 | No changes needed
114 |
115 | ### Version 0.13.2 -> Version 0.13.3
116 |
117 | No changes needed
118 |
119 | ### Version 0.13.1 -> Version 0.13.2
120 |
121 | No changes needed
122 |
123 | ### Version 0.13.0 -> Version 0.13.1
124 |
125 | No changes needed
126 |
--------------------------------------------------------------------------------
/benchmark/api-key-encryption.js:
--------------------------------------------------------------------------------
1 | var stormpath = require('../');
2 | var uuid = require('uuid');
3 | var base64 = require('../lib/utils').base64;
4 | var Benchmark = require('benchmark');
5 | var async = require('async');
6 |
7 | function invoke(app,apiKey,cb){
8 | app.authenticateApiRequest({
9 | request:{
10 | method: 'GET',
11 | url: '/',
12 | headers:{
13 | 'authorization': 'Basic '+ base64.encode(apiKey.id+':'+apiKey.secret)
14 | }
15 | }
16 | },cb);
17 | }
18 |
19 | function addTestRunner(apiKey,test,suite,done){
20 | var client = new stormpath.Client({
21 | apiKey: new stormpath.ApiKey(
22 | process.env['STORMPATH_API_KEY_ID'],
23 | process.env['STORMPATH_API_KEY_SECRET']
24 | ),
25 | apiKeyEncryptionOptions: test.apiKeyEncryptionOptions
26 | });
27 |
28 | client.getApplication(process.env['STORMPATH_APP_HREF'],function(err,app) {
29 |
30 | if(err){ throw err; }
31 |
32 | // Make an initial invocation to warm the cache
33 |
34 | invoke(app,apiKey,function(err){
35 | if(err){ throw err; }
36 | suite.add(test.title, {
37 | defer: true,
38 | fn: function(deferred){
39 | invoke(app,apiKey,function(err){
40 | if(err){
41 | throw err;
42 | }else{
43 | deferred.resolve();
44 | }
45 | });
46 | }
47 | });
48 | done();
49 | });
50 | });
51 | }
52 |
53 |
54 |
55 | var tests = [
56 | {
57 | title: 'With encryption DISABLED (encryptSecret: false) ',
58 | apiKeyEncryptionOptions: {
59 | encryptSecret: false
60 | }
61 | },
62 | {
63 | title: 'With encryption ENABLED (default options) '
64 | },
65 | {
66 | title: 'With light encryption (128 key size, iterations) ',
67 | apiKeyEncryptionOptions: {
68 | encryptionKeySize: 128,
69 | encryptionKeyIterations: 128
70 | }
71 | },
72 | {
73 | title: 'With medium encryption (128 key size, iterations)',
74 | apiKeyEncryptionOptions: {
75 | encryptionKeySize: 256,
76 | encryptionKeyIterations: 512
77 | }
78 | }
79 | ];
80 |
81 |
82 | console.log('Construct Client');
83 |
84 | // First client is used to create our dummy account
85 |
86 | var client1 = new stormpath.Client({
87 | apiKey: new stormpath.ApiKey(
88 | process.env['STORMPATH_API_KEY_ID'],
89 | process.env['STORMPATH_API_KEY_SECRET']
90 | )
91 | });
92 |
93 |
94 | var account;
95 |
96 |
97 | var suite = new Benchmark.Suite('api auth')
98 | .on('start', function() {
99 | console.log('Begin benchmarks');
100 | })
101 | .on('cycle', function(event) {
102 | console.log(String(event.target));
103 | })
104 | .on('complete', function() {
105 | console.log('\nFastest is: ' + this.filter('fastest').pluck('name')+'\n');
106 | account.delete(function(err){
107 | if(err){ throw err; }
108 | console.log('Deleted account');
109 | });
110 | });
111 |
112 |
113 | client1.getApplication(process.env['STORMPATH_APP_HREF'],function(err,app1) {
114 |
115 | if(err){ throw err; }
116 |
117 | console.log('Create test account');
118 |
119 | app1.createAccount({
120 | email: uuid()+'@stormpath.com',
121 | password: uuid() + 'ABC1',
122 | givenName: uuid(),
123 | surname: uuid()
124 | },function(err,result){
125 |
126 | if(err){ throw err; }
127 |
128 | account = result;
129 |
130 | account.createApiKey(function(err,apiKey){
131 |
132 | if(err){ throw err; }
133 |
134 | async.parallel(tests.map(function(test){
135 | return addTestRunner.bind(null,apiKey,test,suite);
136 | }),function(err){
137 | if(err){ throw err; }
138 | suite.run({async:true});
139 | });
140 |
141 | });
142 | });
143 | });
144 |
--------------------------------------------------------------------------------
/docs-dev.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | npm run docs
4 | ./node_modules/httpster/bin/httpster -d ./apidocs &
5 | open http://localhost:3333
6 | ./node_modules/nodemon/bin/nodemon.js -w ./docs/JSDOC.md -w lib/ -x "npm run docs" -e js
--------------------------------------------------------------------------------
/docs/develop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | npm run docs
4 | ./node_modules/httpster/bin/httpster -d ./apidocs &
5 | open http://localhost:3333
6 | ./node_modules/nodemon/bin/nodemon.js -w JSDOC.md -w lib/ -x "npm run docs" -e js
--------------------------------------------------------------------------------
/docs/jsdoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "plugins/markdown"
4 | ],
5 | "templates": {
6 | "linenums": true,
7 | "outputSourceFiles": false,
8 | "outputSourcePath": true,
9 | "systemName": "Stormpath Node SDK",
10 | "theme": "cosmo"
11 | },
12 | "opts": {
13 | "template": "./docs/template"
14 | }
15 | }
--------------------------------------------------------------------------------
/docs/template/jsdoc.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "tags": {
3 | "allowUnknownTags": true
4 | },
5 | "plugins": ["plugins/markdown"],
6 | "templates": {
7 | "logoFile": "",
8 | "cleverLinks": false,
9 | "monospaceLinks": false,
10 | "dateFormat": "ddd MMM Do YYYY",
11 | "outputSourceFiles": true,
12 | "outputSourcePath": true,
13 | "systemName": "DocStrap",
14 | "footer": "",
15 | "copyright": "DocStrap Copyright © 2012-2015 The contributors to the JSDoc3 and DocStrap projects.",
16 | "navType": "vertical",
17 | "theme": "cosmo",
18 | "linenums": true,
19 | "collapseSymbols": false,
20 | "inverseNav": true,
21 | "protocol": "html://",
22 | "methodHeadingReturns": false
23 | },
24 | "markdown": {
25 | "parser": "gfm",
26 | "hardwrap": true
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/docs/template/static/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stormpath/stormpath-sdk-node/da1d653d02a276296a0fc2616689c852d2c0db90/docs/template/static/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/docs/template/static/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stormpath/stormpath-sdk-node/da1d653d02a276296a0fc2616689c852d2c0db90/docs/template/static/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/docs/template/static/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stormpath/stormpath-sdk-node/da1d653d02a276296a0fc2616689c852d2c0db90/docs/template/static/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/docs/template/static/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stormpath/stormpath-sdk-node/da1d653d02a276296a0fc2616689c852d2c0db90/docs/template/static/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/docs/template/static/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stormpath/stormpath-sdk-node/da1d653d02a276296a0fc2616689c852d2c0db90/docs/template/static/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/docs/template/static/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stormpath/stormpath-sdk-node/da1d653d02a276296a0fc2616689c852d2c0db90/docs/template/static/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/docs/template/static/scripts/fulltext-search-ui.js:
--------------------------------------------------------------------------------
1 | window.SearcherDisplay = (function($) {
2 | /**
3 | * This class provides support for displaying quick search text results to users.
4 | */
5 | function SearcherDisplay() { }
6 |
7 | SearcherDisplay.prototype.init = function() {
8 | this._displayQuickSearch();
9 | };
10 |
11 | /**
12 | * This method creates the quick text search entry in navigation menu and wires all required events.
13 | */
14 | SearcherDisplay.prototype._displayQuickSearch = function() {
15 | var quickSearch = $(document.createElement("iframe")),
16 | body = $("body"),
17 | self = this;
18 |
19 | quickSearch.attr("src", "quicksearch.html");
20 | quickSearch.css("width", "0px");
21 | quickSearch.css("height", "0px");
22 |
23 | body.append(quickSearch);
24 |
25 | $(window).on("message", function(msg) {
26 | var msgData = msg.originalEvent.data;
27 |
28 | if (msgData.msgid != "docstrap.quicksearch.done") {
29 | return;
30 | }
31 |
32 | var results = msgData.results || [];
33 |
34 | self._displaySearchResults(results);
35 | });
36 |
37 | function startSearch() {
38 | var searchTerms = $('#search-input').prop("value");
39 | if (searchTerms) {
40 | quickSearch[0].contentWindow.postMessage({
41 | "searchTerms": searchTerms,
42 | "msgid": "docstrap.quicksearch.start"
43 | }, "*");
44 | }
45 | }
46 |
47 | $('#search-input').on('keyup', function(evt) {
48 | if (evt.keyCode != 13) {
49 | return;
50 | }
51 | startSearch();
52 | return false;
53 | });
54 | $('#search-submit').on('click', function() {
55 | startSearch();
56 | return false;
57 | });
58 | };
59 |
60 | /**
61 | * This method displays the quick text search results in a modal dialog.
62 | */
63 | SearcherDisplay.prototype._displaySearchResults = function(results) {
64 | var resultsHolder = $($("#searchResults").find(".modal-body")),
65 | fragment = document.createDocumentFragment(),
66 | resultsList = document.createElement("ul");
67 |
68 | resultsHolder.empty();
69 |
70 | for (var idx = 0; idx < results.length; idx++) {
71 | var result = results[idx],
72 | item = document.createElement("li"),
73 | link = document.createElement("a");
74 |
75 | link.href = result.id;
76 | link.innerHTML = result.title;
77 |
78 | item.appendChild(link)
79 | resultsList.appendChild(item);
80 | }
81 |
82 | fragment.appendChild(resultsList);
83 | resultsHolder.append(fragment);
84 |
85 | $("#searchResults").modal({"show": true});
86 | };
87 |
88 | return new SearcherDisplay();
89 | })($);
90 |
--------------------------------------------------------------------------------
/docs/template/static/scripts/fulltext-search.js:
--------------------------------------------------------------------------------
1 | window.Searcher = (function() {
2 | function Searcher() {
3 | this._index = lunr(function () {
4 | this.field('title', {boost: 10})
5 | this.field('body')
6 | this.ref('id')
7 | }) ;
8 |
9 | this._indexContent = undefined;
10 | }
11 |
12 | Searcher.prototype.init = function() {
13 | var self = this;
14 |
15 | $("script[type='text/x-docstrap-searchdb']").each(function(idx, item) {
16 | self._indexContent = JSON.parse(item.innerHTML);
17 |
18 | for (var entryId in self._indexContent) {
19 | self._index.add(self._indexContent[entryId]);
20 | }
21 | });
22 | };
23 |
24 | Searcher.prototype.search = function(searchTerm) {
25 | var results = [],
26 | searchResults = this._index.search(searchTerm);
27 |
28 | for (var idx = 0; idx < searchResults.length; idx++) {
29 | results.push(this._indexContent[searchResults[idx].ref])
30 | }
31 |
32 | return results;
33 | };
34 |
35 | return new Searcher();
36 | })();
--------------------------------------------------------------------------------
/docs/template/static/scripts/prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | PR.registerLangHandler(PR.createSimpleLexer([
2 | ["pln", /^[\t\n\f\r ]+/, null, " \t\r\n"]
3 | ], [
4 | ["str", /^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/, null],
5 | ["str", /^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/, null],
6 | ["lang-css-str", /^url\(([^"')]*)\)/i],
7 | ["kwd", /^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i, null],
8 | ["lang-css-kw", /^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],
9 | ["com", /^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],
10 | ["com", /^(?:<\!--|--\>)/],
11 | ["lit", /^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],
12 | ["lit", /^#[\da-f]{3,6}/i],
13 | ["pln", /^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],
14 | ["pun", /^[^\s\w"']+/]
15 | ]), ["css"]);
16 | PR.registerLangHandler(PR.createSimpleLexer([], [
17 | ["kwd", /^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]
18 | ]), ["css-kw"]);
19 | PR.registerLangHandler(PR.createSimpleLexer([], [
20 | ["str", /^[^"')]+/]
21 | ]), ["css-str"]);
--------------------------------------------------------------------------------
/docs/template/tmpl/augments.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/template/tmpl/example.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/docs/template/tmpl/examples.tmpl:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/docs/template/tmpl/exceptions.tmpl:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
11 | -
12 |
13 | -
14 | Type
15 |
16 | -
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/docs/template/tmpl/fires.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/docs/template/tmpl/mainpage.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/docs/template/tmpl/members.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Type:
22 |
27 |
28 |
29 |
30 |
31 |
32 | Example 1? 's':'' ?>
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/docs/template/tmpl/method.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Extends:
23 |
24 |
25 |
26 |
27 | Type:
28 |
29 |
30 |
31 | This:
32 |
33 |
34 |
35 | Parameters:
36 |
37 |
38 |
39 |
40 |
41 |
42 | Requires:
43 |
46 |
47 |
48 |
49 | Fires:
50 |
53 |
54 |
55 |
56 | Listens to Events:
57 |
60 |
61 |
62 |
63 | Listeners of This Event:
64 |
67 |
68 |
69 |
70 | Throws:
71 | 1) { ?>
77 |
78 |
80 |
81 |
82 | Returns:
83 | 1) { ?>
89 |
90 |
92 |
93 |
94 | Example 1? 's':'' ?>
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/docs/template/tmpl/params.tmpl:
--------------------------------------------------------------------------------
1 |
41 |
42 |
43 |
44 |
45 |
46 | Name |
47 |
48 |
49 | Type |
50 |
51 |
52 | Argument |
53 |
54 |
55 |
56 | Default |
57 |
58 |
59 | Description |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
71 |
72 |
|
73 |
74 |
75 |
76 |
77 |
78 |
79 | |
80 |
81 |
82 |
83 |
84 | <optional>
85 |
86 |
87 |
88 | <nullable>
89 |
90 |
91 |
92 | <repeatable>
93 |
94 | |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | |
103 |
104 |
105 |
106 | Properties
107 |
108 | |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/docs/template/tmpl/properties.tmpl:
--------------------------------------------------------------------------------
1 |
40 |
41 |
42 |
43 |
44 |
45 | Name |
46 |
47 |
48 | Type |
49 |
50 |
51 | Argument |
52 |
53 |
54 |
55 | Default |
56 |
57 |
58 | Description |
59 |
60 |
61 |
62 |
63 |
68 |
69 |
70 |
71 |
|
72 |
73 |
74 |
75 |
76 |
77 |
78 | |
79 |
80 |
81 |
82 |
83 | <optional>
84 |
85 |
86 |
87 | <nullable>
88 |
89 | |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | |
98 |
99 |
100 |
101 | Properties
102 | |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/docs/template/tmpl/quicksearch.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/docs/template/tmpl/returns.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | -
13 | Type
14 |
15 | -
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/docs/template/tmpl/sections.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/docs/template/tmpl/source.tmpl:
--------------------------------------------------------------------------------
1 |
4 |
10 |
--------------------------------------------------------------------------------
/docs/template/tmpl/tutorial.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 0) { ?>
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/docs/template/tmpl/type.tmpl:
--------------------------------------------------------------------------------
1 |
5 |
6 | |
7 |
8 |
--------------------------------------------------------------------------------
/lib/authc/ApiKey.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | function ApiKey(id, secret) {
6 | this.id = id;
7 | this.secret = secret;
8 | }
9 | utils.inherits(ApiKey, Object);
10 |
11 | ApiKey.prototype.toString = function apiKeyToString() {
12 | return 'id: ' + this.id + ', secret:
';
13 | };
14 |
15 | module.exports = ApiKey;
16 |
17 |
--------------------------------------------------------------------------------
/lib/authc/ApiKeyEncryptedOptions.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var uuid = require('uuid');
4 |
5 | var utils = require('../utils');
6 |
7 | function ApiKeyEncryptedOptions(options) {
8 | options = typeof options === 'object' ? options : {};
9 | this.expand = "account";
10 |
11 | if(options.id){
12 | this.id = options.id;
13 | }
14 |
15 | if(options.encryptSecret !== false){
16 | this.encryptSecret = true;
17 | this.encryptionKeySize = options.encryptionKeySize || 256;
18 | this.encryptionKeyIterations = options.encryptionKeyIterations || 1024;
19 | var salt = new Buffer(uuid().substr(0,16),'base64').toString('base64');
20 | this.encryptionKeySalt = utils.base64.urlEncode(salt);
21 | }
22 | }
23 | utils.inherits(ApiKeyEncryptedOptions, Object);
24 |
25 | module.exports = ApiKeyEncryptedOptions;
26 |
--------------------------------------------------------------------------------
/lib/authc/ApiKeyLoader.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var propsParser = require('properties-parser');
4 |
5 | var _ = require('../underscore');
6 | var ApiKey = require('./ApiKey');
7 |
8 | var FILE_URL_PREFIX = 'file://';
9 | var DEFAULT_ID_PROP_NAME = 'apiKey.id';
10 | var DEFAULT_SECRET_PROP_NAME = 'apiKey.secret';
11 |
12 | function loadFile(path, callback) {
13 | return propsParser.read(path, function(err, props) {
14 | if (err) {
15 | return callback(new Error("Unable to read properties file '" + path + "': " + err.message), null);
16 | }
17 |
18 | var apiKey = new ApiKey(props[DEFAULT_ID_PROP_NAME], props[DEFAULT_SECRET_PROP_NAME]);
19 | return callback(null, apiKey);
20 | });
21 | }
22 |
23 | function loadApiKey(path, callback) {
24 | if (_(path).startsWith(FILE_URL_PREFIX)) {
25 | path = path.substring(FILE_URL_PREFIX.length);
26 | }
27 | loadFile(path, callback);
28 | }
29 |
30 | module.exports = loadApiKey;
31 |
--------------------------------------------------------------------------------
/lib/authc/AssertionAuthenticationResult.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Account = require('../resource/Account');
4 |
5 | /**
6 | * Encapsulates the authentication result from an instance of {@link StormpathAssertionAuthenticator}.
7 | *
8 | * This class should not be manually constructed. It should be obtained from one of these methods:
9 | *
10 | * - {@link StormpathAssertionAuthenticator#authenticate StormpathAssertionAuthenticator.authenticate()}.
11 | *
12 | * @class
13 | */
14 | function AssertionAuthenticationResult(dataStore, data) {
15 | Object.defineProperty(this, 'dataStore', {
16 | enumerable:false,
17 | value: dataStore
18 | });
19 |
20 | // Copy data properties.
21 | if (data) {
22 | for (var key in data) {
23 | if (key in this) {
24 | continue;
25 | }
26 | this[key] = data[key];
27 | }
28 | }
29 | }
30 |
31 | /**
32 | * @function
33 | *
34 | * @description Get the account resource of the account that has authenticated.
35 | *
36 | * @param {Function} callback
37 | *
38 | * The callback to call with the parameters (err, {@link Account}).
39 | */
40 | AssertionAuthenticationResult.prototype.getAccount = function getAccount(callback) {
41 | if (!this.account || !this.account.href) {
42 | return callback(new Error('Unable to get account. Account HREF not specified.'));
43 | }
44 |
45 | this.dataStore.getResource(this.account.href, Account, callback);
46 | };
47 |
48 | module.exports = AssertionAuthenticationResult;
49 |
--------------------------------------------------------------------------------
/lib/authc/AuthRequestParser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var url = require('url');
4 |
5 | var ApiAuthRequestError = require('../error/ApiAuthRequestError');
6 |
7 | function AuthRequestParser(request,locationsToSearch){
8 |
9 | if(typeof request !=='object'){
10 | throw new ApiAuthRequestError({userMessage: 'request must be an object'});
11 | }
12 | if(typeof request.url !== 'string'){
13 | throw new ApiAuthRequestError({userMessage: 'request must have a url string'});
14 | }
15 | if(typeof request.headers !== 'object'){
16 | throw new ApiAuthRequestError({userMessage: 'request must have a headers object'});
17 | }
18 | if(typeof request.method !== 'string'){
19 | throw new ApiAuthRequestError({userMessage: 'request must have a method property'});
20 | }
21 | if(typeof locationsToSearch !== 'object') {
22 | throw new ApiAuthRequestError({userMessage: 'locationsToSearch must be an array'});
23 | }
24 |
25 | var req = request;
26 | var searchBody = locationsToSearch.indexOf('body') > -1;
27 | var searchHeader = locationsToSearch.indexOf('header') > -1;
28 | var searchUrl = locationsToSearch.indexOf('url') > -1;
29 |
30 | var urlParams = url.parse(req.url,true).query;
31 |
32 | this.body = (searchBody && (typeof req.body === 'object') && (req.body !== null)) ? req.body : {};
33 | this.headers = searchHeader ? req.headers : {};
34 |
35 | this.grantType = this.body.grant_type || urlParams.grant_type || '';
36 | this.authorizationValue = searchHeader ?
37 | (this.headers['authorization'] || this.headers['Authorization'] || '') : '';
38 | this.accessToken = searchUrl ?
39 | (urlParams.access_token || this.body.access_token || this.authorizationValue) :
40 | (this.body.access_token || this.authorizationValue);
41 |
42 | this.requestedScope = (this.body.scope || urlParams.scope || '').split(' ');
43 | }
44 |
45 | module.exports = AuthRequestParser;
46 |
--------------------------------------------------------------------------------
/lib/authc/BasicApiAuthenticator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var ApiAuthRequestError = require('../error/ApiAuthRequestError');
4 | var AuthenticationResult = require('../resource/AuthenticationResult');
5 |
6 | function BasicApiAuthenticator(application,authHeaderValue, ttl){
7 | var parts = new Buffer(authHeaderValue.replace(/Basic /i,''),'base64').toString('utf8').split(':');
8 |
9 | if(parts.length !== 2){
10 | return new ApiAuthRequestError({userMessage: 'Invalid Authorization value', statusCode: 400});
11 | }
12 |
13 | this.application = application;
14 | this.id = parts[0];
15 | this.secret = parts[1];
16 |
17 | this.ttl = ttl || 3600;
18 | }
19 |
20 | BasicApiAuthenticator.prototype.authenticate = function authenticate(callback) {
21 | var self = this;
22 |
23 | self.application.getApiKey(self.id,function(err,apiKey){
24 | if(err){
25 | callback(err.status===404 ? new ApiAuthRequestError({userMessage: 'Invalid Client Credentials', error: 'invalid_client', statusCode: 401}) : err);
26 | }else{
27 | if(
28 | (apiKey.secret===self.secret) &&
29 | (apiKey.status==='ENABLED') &&
30 | (apiKey.account.status==='ENABLED')
31 | ){
32 | var authenticationResult = new AuthenticationResult(apiKey,self.application.dataStore);
33 |
34 | authenticationResult.application = self.application;
35 | authenticationResult.ttl = self.ttl;
36 |
37 | callback(null,authenticationResult);
38 | }else{
39 | callback(new ApiAuthRequestError({userMessage: 'Invalid Client Credentials', error: 'invalid_client', statusCode: 401}));
40 | }
41 | }
42 | });
43 | };
44 |
45 | module.exports = BasicApiAuthenticator;
46 |
--------------------------------------------------------------------------------
/lib/authc/BasicRequestAuthenticator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var RequestAuthenticator = require('./RequestAuthenticator');
4 | var utils = require('../utils');
5 |
6 | function BasicRequestAuthenticator() {
7 | BasicRequestAuthenticator.super_.apply(this, arguments);
8 | }
9 | utils.inherits(BasicRequestAuthenticator, RequestAuthenticator);
10 |
11 | BasicRequestAuthenticator.prototype.authenticate = function basicAuthenticate(request) {
12 | var concat = this.apiKey.id + ':' + this.apiKey.secret;
13 | var base64 = utils.base64.encode(concat);
14 | request.headers['Authorization'] = 'Basic ' + base64;
15 | };
16 |
17 | module.exports = BasicRequestAuthenticator;
18 |
--------------------------------------------------------------------------------
/lib/authc/ClientCredentialGrantAuthenticator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function OAuthClientCredentialGrantRequestAuthenticator(application) {
4 | if (!(this instanceof OAuthClientCredentialGrantRequestAuthenticator)) {
5 | return new OAuthClientCredentialGrantRequestAuthenticator(application);
6 | }
7 | this.application = application;
8 | }
9 | OAuthClientCredentialGrantRequestAuthenticator.prototype.authenticate = function authenticate() {
10 | // TODO
11 | };
12 |
13 | module.exports = OAuthClientCredentialGrantRequestAuthenticator;
14 |
--------------------------------------------------------------------------------
/lib/authc/RequestAuthenticator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function RequestAuthenticator(apiKey) {
4 | if (!apiKey) {
5 | throw new Error('apiKey is required.');
6 | }
7 | if (!apiKey.id) {
8 | throw new Error('apiKey.id is required.');
9 | }
10 | if (!apiKey.secret) {
11 | throw new Error('apiKey.secret is required.');
12 | }
13 | this.apiKey = apiKey;
14 | }
15 | //All subclass types must have an 'authenticate' prototype function
16 |
17 | module.exports = RequestAuthenticator;
--------------------------------------------------------------------------------
/lib/authc/StormpathAssertionAuthenticator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var njwt = require('njwt');
4 | var AssertionAuthenticationResult = require('./AssertionAuthenticationResult');
5 |
6 | /**
7 | * @class
8 | *
9 | * @description
10 | *
11 | * Creates an authenticator that can be used to verify a Stormpath Token that was
12 | * provided when the user returned from ID Site, or a SAML callback. This method
13 | * only verifies the token and provides you with any errors. After using this
14 | * authenticator you will likely want to use the {@link OAuthStormpathTokenAuthenticator}
15 | * to generate an Access + Refresh token pair for the user.
16 | *
17 | * Note: this authenticator is bound to the API Key Pair of the client that
18 | * fetched the application resource that you pass to the constructor.
19 | *
20 | * @param {Application} application The Stormpath Application to authenticate against.
21 | *
22 | * @example
23 | * var appHref = 'https://api.stormpath.com/v1/applications/3WIeKpaEjPHfLmy6GIvbwv';
24 | *
25 | * client.getApplication(appHref, function(err, application) {
26 | * var authenticator = new stormpath.StormpathAssertionAuthenticator(application);
27 | * });
28 | */
29 | function StormpathAssertionAuthenticator(application) {
30 | Object.defineProperty(this, 'dataStore', {
31 | enumerable:false,
32 | value: application.dataStore
33 | });
34 |
35 | this.secret = this.dataStore.requestExecutor.options.client.apiKey.secret;
36 | }
37 |
38 | /**
39 | * Exchange the Stormpath Token for an Access and Refresh token.
40 | *
41 | * @param {Object} tokenRequest
42 | * An object to encapsulate the request.
43 | *
44 | * @param {String} tokenRequest.stormpath_token
45 | * The Stormpath Token, from the ID Site or SAML callback. This is a compacted JWT string.
46 | *
47 | * @param {Function} callback
48 | * Callback function, will be called with (err, {@link AssertionAuthenticationResult}).
49 | *
50 | * @example
51 | *
52 | * var stormpathToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzRHZNZ2JOVFEwZkhuS3BHd1VHUlB4IiwiaWF0IjoxNDcwMjU4MDc0LCJpc3MiOiJodHRwczovL2FwaS5zdG9ybXBhdGguY29tL3YxL2FwcGxpY2F0aW9ucy8yNGs3SG5ET3o0dFE5QVJzbVZ6YUNJIiwic3ViIjoiaHR0cHM6Ly9hcGkuc3Rvcm1wYXRoLmNvbS92MS9hY2NvdW50cy8xdWxlM3dKbkxZVUw3VVE2OGFBdlJaOWwiLCJleHAiOjE0NzAyNjk0MTJ9.i4OWcqczU-us71zT2XIiL69s2srJ7YPH5mAzrw8rNE8';
53 | *
54 | * authenticator.authenticate(stormpathToken, function(err, assertionAuthenticationResult) {
55 | * assertionAuthenticationResult.getAccount(function(err, account){
56 | * if (err) {
57 | * // an error occured on ID Site or during the SAML authentication flow
58 | * console.error(err);
59 | * return;
60 | * }
61 | * console.log(account.email + ' has authenticated');
62 | * });
63 | * });
64 | */
65 | StormpathAssertionAuthenticator.prototype.authenticate = function authenticate(stormpathToken, callback) {
66 | var dataStore = this.dataStore;
67 | njwt.verify(stormpathToken, this.secret, function (err, jwt) {
68 | if (err) {
69 | err.statusCode = 401;
70 | return callback(err);
71 | }
72 |
73 | if (jwt.body.err){
74 | return callback(jwt.body.err);
75 | }
76 |
77 | var account = null;
78 |
79 | // For Stormpath mapped JWT fields, see:
80 | // https://docs.stormpath.com/rest/product-guide/latest/005_auth_n.html#step-5-stormpath-response-with-jwt
81 | if (jwt.body.sub) {
82 | account = {
83 | href: jwt.body.sub
84 | };
85 | }
86 |
87 | callback(null, new AssertionAuthenticationResult(
88 | dataStore, {
89 | stormpath_token: stormpathToken,
90 | expandedJwt: jwt,
91 | account: account
92 | }
93 | ));
94 | });
95 |
96 | return this;
97 | };
98 |
99 | module.exports = StormpathAssertionAuthenticator;
100 |
--------------------------------------------------------------------------------
/lib/authc/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var BasicRequestAuthenticator = require('./BasicRequestAuthenticator');
4 | var Sauthc1RequestAuthenticator = require('./Sauthc1RequestAuthenticator');
5 |
6 | /**
7 | * @private
8 | *
9 | * @description
10 | *
11 | * A factory function that inspects any options and returns an appropriate {@link RequestAuthenticator} to use to
12 | * authenticate requests submitted to the API server.
13 | *
14 | * @param {object} options
15 | * @param {Sauthc1RequestAuthenticator|BasicRequestAuthenticator=} options.requestAuthenticator
16 | * @param {string} options.authenticationScheme - name of auth method that will instantiated
17 | * @returns {BasicRequestAuthenticator|Sauthc1RequestAuthenticator}
18 | */
19 | function getAuthenticator(options) {
20 |
21 | if (options.requestAuthenticator) {
22 | return options.requestAuthenticator;
23 | }
24 |
25 | var apiKey = options.client ? options.client.apiKey : options.apiKey;
26 |
27 | if (!apiKey) {
28 | throw new Error('If you do not specify a \'requestAuthenticator\' field, you must specify an ApiKey.');
29 | }
30 |
31 | var authc = new BasicRequestAuthenticator(apiKey); //default until Sauthc1 is working.
32 |
33 | if (options.authenticationScheme) {
34 | var scheme = options.authenticationScheme.toUpperCase();
35 |
36 | if (scheme === 'SAUTHC1') {
37 | authc = new Sauthc1RequestAuthenticator(apiKey);
38 | } else if (scheme === 'BASIC') {
39 | authc = new BasicRequestAuthenticator(apiKey);
40 | } else {
41 | throw new Error("Unrecognized authentication scheme: " + options.authenticationScheme);
42 | }
43 | }
44 |
45 | return authc;
46 | }
47 |
48 | module.exports = {
49 | ApiKey: require('./ApiKey'),
50 | loadApiKey: require('./ApiKeyLoader'),
51 | getAuthenticator: getAuthenticator
52 | };
53 |
--------------------------------------------------------------------------------
/lib/cache/Cache.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _ = require('underscore');
4 | var CacheEntry = require('./CacheEntry');
5 | var CacheStats = require('./CacheStats');
6 | var MemoryStore = require('./MemoryStore');
7 |
8 | var defaults = {
9 | store: MemoryStore,
10 | ttl: 5 * 60,
11 | tti: 5 * 60
12 | };
13 |
14 | /**
15 | * @private
16 | *
17 | * @description
18 | *
19 | * Cache abstractions
20 | * A unified interface to different implementations of data caching.
21 | *
22 | * @param [store=MemoryStore]
23 | * @param {number=} [ttl=5*60] - time to live in seconds
24 | * @param {number=} [tti=5*60] - time to idle in seconds
25 | * @params {object} options - cache configuration options
26 | * @constructor
27 | */
28 | function Cache(options) {
29 | options = options || {};
30 |
31 | if (!(this instanceof Cache)) {
32 | return new Cache(options);
33 | }
34 |
35 | if (typeof options === 'function'){
36 | options = { store: options };
37 | }
38 |
39 | _.defaults(options, defaults);
40 | var Store = options.store;
41 |
42 | this.ttl = options.ttl;
43 | this.tti = options.tti;
44 | this.store = new Store(options);
45 | this.stats = new CacheStats();
46 | }
47 |
48 | Cache.prototype.get = function (key, cb) {
49 |
50 | var self = this;
51 |
52 | self.store.get(key, function (err, entry) {
53 | if (err || !entry) {
54 | return cb(err, null);
55 | }
56 |
57 | if (entry.isExpired(self.ttl, self.tti)) {
58 | self.stats.miss(true);
59 | return self.store.delete(key, function (err) {
60 | return cb(err, null);
61 | });
62 | }
63 |
64 | self.stats.hit();
65 | // what point to touch entry if we not updating cache store
66 | // will work for memory store but will not for redis store
67 |
68 | if (self.ttl !== self.tti) {
69 | entry.touch();
70 | self.store.set(key, entry, function(){});
71 | }
72 |
73 | return cb(null, entry.value);
74 | });
75 | };
76 |
77 | /**
78 | *
79 | * @param key
80 | * @param value
81 | * @param {boolean|function} [_new=true]
82 | * @param {function} cb
83 | */
84 | Cache.prototype.put = function (key, value, _new, cb) {
85 | if (typeof _new === 'function') {
86 | cb = _new;
87 | _new = true;
88 | }
89 | this.stats.put(_new);
90 | this.store.set(key, new CacheEntry(value), cb);
91 | };
92 |
93 | Cache.prototype.delete = function (key, cb) {
94 | this.stats.delete();
95 | this.store.delete(key, cb);
96 | };
97 |
98 | Cache.prototype.clear = function (cb) {
99 | this.stats.clear();
100 | this.store.clear(cb);
101 | };
102 |
103 | Cache.prototype.size = function (cb) {
104 | this.store.size(cb);
105 | };
106 |
107 | module.exports = Cache;
108 |
--------------------------------------------------------------------------------
/lib/cache/CacheEntry.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var moment = require('moment');
4 |
5 | /**
6 | * @private
7 | *
8 | * @description
9 | *
10 | * Cache entry abstraction
11 | * A single entry inside a cache
12 | *
13 | * It contains the data as originally returned by Stormpath along
14 | * with additional metadata like timestamps.
15 | * @param {object} value - value to store in cache
16 | * @param {Date=} createdAt - time when cache entry created
17 | * @param {Date=} lastAccessedAt - time when cache entry was last accessed
18 | * @constructor
19 | */
20 | function CacheEntry(value, createdAt, lastAccessedAt){
21 | this.value = value;
22 | this.createdAt = createdAt || Date.now();
23 | this.lastAccessedAt = lastAccessedAt || this.createdAt;
24 |
25 | if (typeof this.createdAt !== 'number' ||
26 | typeof this.lastAccessedAt !== 'number'){
27 | throw new Error('Expecting date in timestamp format or use CacheEntry.parse method instead');
28 | }
29 | }
30 |
31 | // todo: what does it do in py: datetime.timedelta
32 | function timedelta(seconds){return seconds * 1000;}
33 |
34 | /**
35 | * Changes last accessed to current
36 | */
37 | CacheEntry.prototype.touch = function touch(){
38 | this.lastAccessedAt = Date.now();
39 | };
40 |
41 | /**
42 | * Checks is entry expired due to overdue of live or idle timeouts
43 | * @param {number=} ttl - time to live
44 | * @param {number=} tti - time to idle
45 | * @returns {boolean}
46 | */
47 | CacheEntry.prototype.isExpired = function isExpired(ttl, tti){
48 | var now = Date.now();
49 | return (now >= (this.createdAt + timedelta(ttl))) ||
50 | (now >= (this.lastAccessedAt + timedelta(tti)));
51 | };
52 |
53 | CacheEntry.prototype.toObject = function(){
54 | function printDate(val){
55 | return moment.utc(val).format('YYYY-MM-DD HH:mm:ss.SSS');
56 | }
57 | return {
58 | createdAt: printDate(this.createdAt),
59 | lastAccessedAt: printDate(this.lastAccessedAt),
60 | value: this.value
61 | };
62 | };
63 |
64 | CacheEntry.parse = function(data){
65 | function parseDate(val){
66 | return moment.utc(val).valueOf();
67 | }
68 | return new CacheEntry(data.value,
69 | parseDate(data.createdAt),
70 | parseDate(data.lastAccessedAt));
71 | };
72 |
73 | module.exports = CacheEntry;
74 |
--------------------------------------------------------------------------------
/lib/cache/CacheManager.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Cache = require('./Cache');
4 |
5 | /**
6 | * @private
7 | *
8 | * @description
9 | *
10 | * Cache manager abstraction.
11 | * Handles all the different caches used by the SDK
12 | * @constructor
13 | */
14 | function CacheManager() {
15 | var self = this;
16 | self.caches = {};
17 |
18 | Object.defineProperty(self, 'stats', {
19 | get: function () {
20 | return Object.keys(self.caches).reduce(function(a,region){
21 | a[region] = self.caches[region].stats;
22 | return a;
23 | },{});
24 | }
25 | });
26 | }
27 |
28 | CacheManager.prototype.createCache = function (region,options) {
29 | this.caches[region] = new Cache(options);
30 | };
31 |
32 | CacheManager.prototype.getCache = function (region) {
33 | return this.caches[region];
34 | };
35 |
36 | module.exports = CacheManager;
--------------------------------------------------------------------------------
/lib/cache/CacheStats.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @private
5 | *
6 | * @description
7 | *
8 | * Cache stats.
9 | * Represents cache statistic
10 | * @constructor
11 | */
12 | function CacheStats() {
13 | this.puts = 0;
14 | this.hits = 0;
15 | this.misses = 0;
16 | this.expirations = 0;
17 | this.size = 0;
18 | }
19 |
20 | /**
21 | *
22 | * @param {boolean} [_new=true]
23 | */
24 | CacheStats.prototype.put = function (_new) {
25 | _new = _new !== false;
26 | this.puts++;
27 | if (_new) {
28 | this.size++;
29 | }
30 | };
31 |
32 | CacheStats.prototype.hit = function () {
33 | this.hits++;
34 | };
35 |
36 | CacheStats.prototype.miss = function (expired) {
37 | this.misses++;
38 | if (expired) {
39 | this.expirations++;
40 | }
41 | };
42 |
43 | CacheStats.prototype.delete = function () {
44 | if (this.size > 0) {
45 | this.size--;
46 | }
47 | };
48 |
49 | CacheStats.prototype.clear = function () {
50 | this.size = 0;
51 | };
52 |
53 | module.exports = CacheStats;
54 |
--------------------------------------------------------------------------------
/lib/cache/DisabledCache.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function DisabledCache() {
4 | }
5 |
6 | DisabledCache.prototype.get =
7 | DisabledCache.prototype.set =
8 | DisabledCache.prototype.delete =
9 | DisabledCache.prototype.clear =
10 | DisabledCache.prototype.size = function () {
11 | return Array.prototype.slice.call(arguments, -1)[0](null, null);
12 | };
13 |
14 | module.exports = DisabledCache;
--------------------------------------------------------------------------------
/lib/cache/MemcachedStore.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Memcached = require('memcached');
4 |
5 | // todo: create store provider and register redis store only for node.js version
6 | var CacheEntry = require('./CacheEntry');
7 |
8 | /**
9 | * @class
10 | *
11 | * @private
12 | *
13 | * @description
14 | *
15 | * Caching implementation that uses Redis as data storage. If an existing
16 | * client instance is not provided, this constructor will create one. Utilizes
17 | * the [memcached library](https://github.com/3rd-Eden/memcached).
18 | *
19 | * @param {Object} [options]
20 | * @param {Object} [options.client] A memcached client instance
21 | * @param {Object|String|Array} [options.connection] Memcached client constructor
22 | * connection string parameter.
23 | * @param {*} [options.*] Other options to pass to the Memcached client constructor.
24 | */
25 | function MemcachedStore(opt){
26 | this._options = opt || {};
27 | this.memcached = opt.client || MemcachedStore._createClient(opt);
28 | }
29 |
30 | MemcachedStore._createClient = function creteMemcachedClient(opt){
31 | return new Memcached(opt.connection, opt.options);
32 | };
33 |
34 | MemcachedStore.prototype.get = function (key, cb){
35 | this.memcached.get(key, function(err, entry){
36 | return cb(err, !entry ? null : CacheEntry.parse(entry));
37 | });
38 | };
39 |
40 | MemcachedStore.prototype.set = function (key, val, cb){
41 | this.memcached.set(key, val, this._options.ttl, cb);
42 | };
43 |
44 | MemcachedStore.prototype.delete = function (key, cb){
45 | this.memcached.del(key, cb);
46 | };
47 |
48 | MemcachedStore.prototype.clear = function (cb){
49 | this.memcached.flush(cb);
50 | };
51 |
52 | MemcachedStore.prototype.size = function (cb){
53 | this.memcached.stats(function(err, stats){
54 | var size = stats && stats.length ? stats[0].curr_items : -1;
55 | cb(err, size);
56 | });
57 | };
58 |
59 | module.exports = MemcachedStore;
60 |
--------------------------------------------------------------------------------
/lib/cache/MemoryStore.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function MemoryStore() {
4 |
5 | var store = {};
6 |
7 | this.get = function get(key, cb) {
8 | return cb(null, store[key]);
9 | };
10 |
11 | this.set = function set(key, val, cb) {
12 | store[key] = val;
13 | return cb(null, val);
14 | };
15 |
16 | this.delete = function del(key, cb) {
17 | delete store[key];
18 | return cb(null);
19 | };
20 |
21 | this.clear = function clear(cb) {
22 | store = {};
23 | cb(null);
24 | };
25 |
26 | this.size = function dbsize(cb) {
27 | cb(null, Object.keys(store).length);
28 | };
29 | }
30 |
31 | module.exports = MemoryStore;
--------------------------------------------------------------------------------
/lib/cache/RedisStore.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var redis = require('redis');
4 |
5 | var CacheEntry = require('./CacheEntry');
6 |
7 | /**
8 | * @class
9 | *
10 | * @private
11 | *
12 | * @description
13 | *
14 | * Caching implementation that uses Redis as data storage. If an existing
15 | * client instance is not provided, this constructor will create one. Utilizes
16 | * the [node-redis](https://github.com/NodeRedis/node_redis) library.
17 | *
18 | * @param {Object} [options]
19 | * @param {Object} [options.client] A redis client instance
20 | * @param {Object} [options.connection] Redis client constructor connection options
21 | * @param {Number} [options.connection.port] DB port number
22 | * @param {String} [options.connection.host] DB host name
23 | * @param {*} [options.*] Other options to pass to the Redis client constructor.
24 | */
25 | function RedisStore(opt){
26 | this._options = opt || {};
27 | this.redis = opt.client || RedisStore._createClient(opt);
28 | this.redis.debug_mode = /redis/i.test(process.env.DEBUG);
29 | }
30 |
31 | RedisStore._createClient = function createRedisClient(opt){
32 | var conn = (opt && opt.connection) || {port:'6379',host:'127.0.0.1'};
33 | return redis.createClient(conn.port, conn.host, opt.options);
34 | };
35 |
36 | RedisStore.prototype.get = function (key, cb){
37 | this.redis.get(key, function(err, entry){
38 | return cb(err, !entry ? null : CacheEntry.parse(JSON.parse(entry)));
39 | });
40 | };
41 |
42 | RedisStore.prototype.set = function (key, val, cb){
43 | var entry = JSON.stringify(val);
44 | this.redis.set(key, entry, cb);
45 | if (this._options.ttl){
46 | this.redis.expire(key, this._options.ttl);
47 | }
48 | };
49 |
50 | RedisStore.prototype.delete = function (key, cb){
51 | this.redis.del(key, cb);
52 | };
53 |
54 | RedisStore.prototype.clear = function (cb){
55 | this.redis.flushdb(cb);
56 | };
57 |
58 | RedisStore.prototype.size = function (cb){
59 | this.redis.dbsize(cb);
60 | };
61 |
62 | module.exports = RedisStore;
63 |
--------------------------------------------------------------------------------
/lib/cache/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | CacheHandler: require('./CacheHandler'),
5 | CacheManager: require('./CacheManager'),
6 | Cache: require('./Cache'),
7 | CacheEntry: require('./CacheEntry'),
8 | CacheStats: require('./CacheStats'),
9 | DisabledCache: require('./DisabledCache'),
10 | MemoryStore: require('./MemoryStore')
11 | };
12 |
13 |
14 |
--------------------------------------------------------------------------------
/lib/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # 'apiKey' might feel redundant since 'client.apiKey' is what is being used.
3 | # But for backward-compability we need to have this here.
4 | apiKey:
5 | file: null
6 | id: null
7 | secret: null
8 | client:
9 | apiKey:
10 | file: null
11 | id: null
12 | secret: null
13 | cacheManager:
14 | defaultTtl: 300
15 | defaultTti: 300
16 | caches:
17 | account:
18 | ttl: 300
19 | tti: 300
20 | baseUrl: "https://api.stormpath.com/v1"
21 | connectionTimeout: 30
22 | authenticationScheme: "SAUTHC1"
23 | proxy:
24 | port: null
25 | host: null
26 | username: null
27 | password: null
28 | application:
29 | name: null
30 | href: null
31 |
--------------------------------------------------------------------------------
/lib/configLoader.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 |
3 | var stormpathConfig = require('stormpath-config');
4 | var strategy = stormpathConfig.strategy;
5 |
6 | // Set the paths the we want to load configuration files from
7 | var currentPath = process.cwd();
8 | var stormpathPath = '~/.stormpath';
9 |
10 | // Create a default client config loader.
11 | module.exports = function (extendWithConfig) {
12 | return new stormpathConfig.Loader([
13 | // Load default configuration.
14 | new strategy.LoadFileConfigStrategy(path.join(__dirname, '/config.yml'), true),
15 |
16 | // Load API keys and configuration from home (.stormpath) folder
17 | new strategy.LoadAPIKeyConfigStrategy(stormpathPath + '/apiKey.properties'),
18 | new strategy.LoadFileConfigStrategy(stormpathPath + '/stormpath.json'),
19 | new strategy.LoadFileConfigStrategy(stormpathPath + '/stormpath.yml'),
20 |
21 | // Load API keys and configuration from app folder
22 | new strategy.LoadAPIKeyConfigStrategy(currentPath + '/apiKey.properties'),
23 | new strategy.LoadFileConfigStrategy(currentPath + '/stormpath.json'),
24 | new strategy.LoadFileConfigStrategy(currentPath + '/stormpath.yml'),
25 |
26 | // Load configuration from our environment.
27 | new strategy.LoadEnvConfigStrategy('STORMPATH', {
28 | // Aliases used to support legacy API key.
29 | STORMPATH_APIKEY_ID: 'STORMPATH_API_KEY_ID',
30 | STORMPATH_APIKEY_SECRET: 'STORMPATH_API_KEY_SECRET',
31 | STORMPATH_APIKEY_FILE: 'STORMPATH_API_KEY_FILE'
32 | }),
33 |
34 | // Extend our configuration with the configuration we passed into the client.
35 | // Also, try and load our API key if it was specified in our config.
36 | new strategy.ExtendConfigStrategy(extendWithConfig),
37 | new strategy.LoadAPIKeyFromConfigStrategy(),
38 |
39 | // Enrich our client config.
40 | new strategy.EnrichClientConfigStrategy(),
41 |
42 | // Validate config so that we know that we have an API key and can continue...
43 | new strategy.ValidateClientConfigStrategy()
44 |
45 | ]);
46 | };
47 |
--------------------------------------------------------------------------------
/lib/ds/NonceStore.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /*
4 | * Deafult NonceStore - requires a data store instance which has a cache manager
5 | */
6 | var NonceStore = function NonceStore(dataStore){
7 | this.cache = dataStore.cacheHandler.cacheManager.getCache('idSiteNonces');
8 | };
9 |
10 | NonceStore.prototype.getNonce = function getNonce(nonceValue,cb) {
11 | this.cache.get(nonceValue,cb);
12 | };
13 |
14 | NonceStore.prototype.putNonce = function putNonce(nonceValue,cb) {
15 | this.cache.put(nonceValue,nonceValue,cb);
16 | };
17 |
18 |
19 | module.exports = NonceStore;
--------------------------------------------------------------------------------
/lib/error/ApiAuthRequestError.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | function ApiAuthRequestError(errorData){
6 | Error.captureStackTrace(this, this.constructor);
7 |
8 | this.name = this.constructor.name;
9 | this.userMessage = this.message = errorData.userMessage;
10 | this.statusCode = errorData.statusCode || 400;
11 | this.error = errorData.error;
12 | }
13 | utils.inherits(ApiAuthRequestError, Error);
14 |
15 | module.exports = ApiAuthRequestError;
16 |
--------------------------------------------------------------------------------
/lib/error/ResourceError.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('./../utils');
4 |
5 | function ResourceError(responseBody, requestData) {
6 | Error.captureStackTrace(this, this.constructor);
7 |
8 | requestData = requestData || {};
9 |
10 | this.name = this.constructor.name;
11 | this.status = responseBody.status;
12 | this.code = responseBody.code;
13 | this.userMessage = responseBody.message;
14 | this.developerMessage = responseBody.developerMessage;
15 | this.moreInfo = responseBody.moreInfo;
16 | this.requestId = responseBody.requestId;
17 | this.url = requestData.url;
18 | this.method = requestData.method;
19 | this.stack = '';
20 |
21 | this.message = 'HTTP ' + this.status +
22 | ', Stormpath ' + this.code + ' (' + this.moreInfo + '): ' +
23 | this.developerMessage;
24 |
25 | if (responseBody.error) {
26 | this.error = responseBody.error;
27 | }
28 | }
29 | utils.inherits(ResourceError, Error);
30 |
31 | module.exports = ResourceError;
32 |
--------------------------------------------------------------------------------
/lib/error/invalid-href.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Produces an Erorr object with a message that indicates which resource type has
5 | * violated an href validation.
6 | *
7 | * @param {string} href The href that was passed into a resource getter.
8 | * @param {string} resourceName The human readable name of the expected resource type.
9 | * @return {Error} A simple error with the message
10 | */
11 | function InvalidHrefError(href, resourceName){
12 | var message = 'Argument \'href\' (' + href + ') is not a valid ' + resourceName +' href.';
13 | return new Error(message);
14 | }
15 |
16 | module.exports = InvalidHrefError;
17 |
--------------------------------------------------------------------------------
/lib/error/messages.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ID_SITE_INVALID_CB_URI: "cb_uri URI must be provided and must be in your ID Site whitelist",
3 | ID_SITE_JWT_INVALID_AUD: "The client used to sign the jwtResponse is different than the one used in this datasore.",
4 | ID_SITE_JWT_HAS_EXPIRED: "Token has expired",
5 | ID_SITE_JWT_ALREADY_USED: "Token has already been used."
6 | };
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('./stormpath');
4 |
--------------------------------------------------------------------------------
/lib/oauth/id-site-grant.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var util = require('util');
4 | var JwtAuthenticationResult = require('../jwt/jwt-authentication-result');
5 |
6 | function OAuthIdSiteTokenGrantAuthenticationResult(application, data){
7 | OAuthIdSiteTokenGrantAuthenticationResult.super_.apply(this, arguments);
8 | this.accessTokenResponse = data;
9 | }
10 | util.inherits(OAuthIdSiteTokenGrantAuthenticationResult, JwtAuthenticationResult);
11 |
12 | /**
13 | * Deprecated, replaced by OAuthStormpathTokenAuthenticator. Will be removed in 1.0.
14 | *
15 | * @private
16 | */
17 | function OAuthIdSiteTokenGrantAuthenticator(application) {
18 | if (!(this instanceof OAuthIdSiteTokenGrantAuthenticator)) {
19 | return new OAuthIdSiteTokenGrantAuthenticator(application);
20 | }
21 |
22 | this.application = application;
23 | }
24 |
25 | OAuthIdSiteTokenGrantAuthenticator.prototype.authenticate = util.deprecate(function authenticate(data, callback) {
26 | var application = this.application;
27 |
28 | var formData = {
29 | grant_type: 'id_site_token',
30 | token: data.id_site_token
31 | };
32 |
33 | var tokenHref = application.href + '/oauth/token';
34 |
35 | application.dataStore.createResource(tokenHref, { form: formData }, function(err, tokenData) {
36 | if (err) {
37 | return callback(err);
38 | }
39 |
40 | callback(null, new OAuthIdSiteTokenGrantAuthenticationResult(application, tokenData));
41 | });
42 | },'OAuthIdSiteTokenGrantAuthenticator is deprecated. Use OAuthStormpathTokenAuthenticator instead. See http://docs.stormpath.com/nodejs/api/oauthStormpathTokenAuthenticator');
43 |
44 | module.exports = {
45 | authenticator: OAuthIdSiteTokenGrantAuthenticator,
46 | authenticationResult: OAuthIdSiteTokenGrantAuthenticationResult
47 | };
48 |
--------------------------------------------------------------------------------
/lib/oauth/stormpath-access-token-authentication-result.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | /**
6 | * @constructor
7 | *
8 | * @description
9 | *
10 | * Encapsulates the access token resource response, obtained from the `/accessTokens` collection.
11 | *
12 | * @param {Client} client
13 | * An initialized Stormpath Client for the tenant the issued the token.
14 | *
15 | * @param {AccessTokenResponse} accessTokenResponse
16 | * The access token response from the Stormpath REST API.
17 | */
18 | function StormpathAccessTokenAuthenticationResult(client, data) {
19 | if (!(this instanceof StormpathAccessTokenAuthenticationResult)) {
20 | return new StormpathAccessTokenAuthenticationResult(client, data);
21 | }
22 |
23 | Object.defineProperty(this, 'client', {
24 | enumerable: false,
25 | value: client
26 | });
27 |
28 | for (var key in data) {
29 | if (data.hasOwnProperty(key)) {
30 | this[key] = data[key];
31 | }
32 | }
33 | }
34 |
35 | /**
36 | * @name StormpathAccessTokenAuthenticationResult#account
37 | *
38 | * @description
39 | *
40 | * An object literal with an href pointer to the account that has authenticated.
41 | * Use {@link StormpathAccessTokenAuthenticationResult#getAccount StormpathAccessTokenAuthenticationResult.getAccount()}
42 | * to fetch the full {@link Account} resource.
43 | *
44 | * @type {Object}
45 | */
46 | StormpathAccessTokenAuthenticationResult.prototype.account = null;
47 |
48 | /**
49 | * An object literal with an href pointer to the application that issued this
50 | * token. Use {@link StormpathAccessTokenAuthenticationResult#getApplication StormpathAccessTokenAuthenticationResult.getApplication()}
51 | * to fetch the full {@link Application} resource.
52 | *
53 | * @type {Object}
54 | */
55 | StormpathAccessTokenAuthenticationResult.prototype.application = null;
56 |
57 | /**
58 | * @name StormpathAccessTokenAuthenticationResult#jwt
59 | *
60 | * @description
61 | *
62 | * The JWT access token string that was provided for authentication.
63 | *
64 | * @type {String}
65 | */
66 | StormpathAccessTokenAuthenticationResult.prototype.jwt = null;
67 |
68 | /**
69 | * @name StormpathAccessTokenAuthenticationResult#expandedJwt
70 | *
71 | * @description
72 | *
73 | * An object that allows you to inspect the body, claims, and header of the
74 | * access token.
75 | *
76 | * @type {Object}
77 | */
78 | StormpathAccessTokenAuthenticationResult.prototype.expandedJwt = null;
79 |
80 | /**
81 | * @function
82 | *
83 | * @description Get the account resource of the account that has authenticated.
84 | *
85 | * @param {ExpansionOptions} options
86 | * Options for expanding the fetched {@link Account} resource.
87 | *
88 | * @param {Function} callback
89 | * The callback to call with the parameters (err, {@link Account}).
90 | */
91 | StormpathAccessTokenAuthenticationResult.prototype.getAccount = function getAccount( /* [options,] callback */ ) {
92 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
93 | this.client.getAccount(this.account.href, args.options, require('../resource/Account'), args.callback);
94 | };
95 |
96 | StormpathAccessTokenAuthenticationResult.prototype.getApplication = function getApplication( /* [options,] callback */ ) {
97 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
98 |
99 | this.client.getApplication(this.application.href, args.options, require('../resource/Application'), args.callback);
100 | };
101 |
102 | module.exports = StormpathAccessTokenAuthenticationResult;
103 |
--------------------------------------------------------------------------------
/lib/proxy/ObjectCallProxy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Create a new ObjectCallProxy.
3 | *
4 | * @class
5 | *
6 | * @private
7 | */
8 | function ObjectCallProxy (source) {
9 | this.source = source;
10 | this.attached = {};
11 | this.pending = [];
12 | }
13 |
14 | /**
15 | * Restore all of the attached methods.
16 | *
17 | * @private
18 | */
19 | ObjectCallProxy.prototype._restore = function () {
20 | for (var name in this.attached) {
21 | this.source[name] = this.attached[name];
22 | delete this.attached[name];
23 | }
24 | };
25 |
26 | /**
27 | * Release all of the pending callbacks.
28 | *
29 | * @private
30 | * @param {Error} [err] - Error to release all callbacks with (optional).
31 | */
32 | ObjectCallProxy.prototype._release = function (err) {
33 | var source = this.source;
34 | var pending = this.pending;
35 |
36 | this.pending = [];
37 |
38 | pending.forEach(function (call) {
39 | var fn = call.fn;
40 | var args = call.args;
41 | var callback = call.callback;
42 |
43 | args[args.length - 1] = function () {
44 | var subArgs = err ? [err] : Array.prototype.slice.call(arguments);
45 | callback.apply(null, subArgs);
46 | };
47 |
48 | fn.apply(source, args);
49 | });
50 | };
51 |
52 | /**
53 | * Attach onto the source object and intercept all calling
54 | * methods with callbacks (where last argument is function).
55 | *
56 | * @param fn [predicateFn] - Predicate to filter methods by (optional).
57 | */
58 | ObjectCallProxy.prototype.attach = function (predicateFn) {
59 | var source = this.source;
60 | var pending = this.pending;
61 | var attached = this.attached;
62 |
63 | if (!predicateFn) {
64 | predicateFn = function () {
65 | return true;
66 | };
67 | }
68 |
69 | function _attach (name) {
70 | if (!(name in attached)) {
71 | var originalFn = source[name];
72 |
73 | attached[name] = originalFn;
74 |
75 | source[name] = function () {
76 | var args = Array.prototype.slice.call(arguments);
77 | var lastArgumentOffset = args.length - 1;
78 |
79 | if (args.length && typeof args[lastArgumentOffset] === 'function') {
80 | pending.push({
81 | args: args,
82 | callback: args[lastArgumentOffset],
83 | fn: originalFn
84 | });
85 | } else {
86 | return originalFn.apply(source, args);
87 | }
88 | };
89 | }
90 | }
91 |
92 | // Proxy all methods on source object.
93 | for (var name in source) {
94 | var value = source[name];
95 |
96 | // If a predicate is provided, then filter accordingly.
97 | if (!predicateFn(name)) {
98 | continue;
99 | }
100 |
101 | if (typeof value === 'function') {
102 | _attach(name);
103 | }
104 | }
105 | };
106 |
107 | /**
108 | * Detach all attached methods and release any pending calls.
109 | *
110 | * @param {Error} [err] - Error to release all callbacks with (optional).
111 | */
112 | ObjectCallProxy.prototype.detach = function (err) {
113 | this._restore();
114 | this._release(err);
115 | };
116 |
117 | module.exports = ObjectCallProxy;
118 |
--------------------------------------------------------------------------------
/lib/resource/AccessToken.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | /**
6 | * @class AccessToken
7 | *
8 | * @description
9 | *
10 | * Encapsulates a Stormpath OAuth Access Token Resource. For full
11 | * documentation of this resource, please see
12 | * [REST API Reference: Access tokens](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#access-tokens).
13 | *
14 | * This class should not be manually constructed. It should be obtained from one
15 | * of these methods:
16 | *
17 | * - From the client, using the access token stormpath href {@link Client#getAccessToken Client.getAccessToken()}
18 | * - From the account, {@link Account#getAccessTokens Account.getAccessTokens()}
19 | * - From a JWT authentication, {@link JwtAuthenticator#authenticate JwtAuthenticator}
20 | * - From an OAuth 2.0 password grant authentication, {@link OAuthPasswordGrantRequestAuthenticator#authenticate OAuthPasswordGrantRequestAuthenticator}
21 | *
22 | * For a high-level overview of token management, please see
23 | * {@link https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#introduction-to-token-based-authentication Introduction to Token-Based Authentication}.
24 | *
25 | * To revoke a access token, invoke the `delete()` method on an instance of
26 | * this class.
27 | *
28 | * @param {Object} accessTokenResource
29 | *
30 | * The JSON representation of this resource, retrieved from the Stormpath REST API.
31 | */
32 | function AccessToken() {
33 | AccessToken.super_.apply(this, arguments);
34 | }
35 |
36 | // TODO: implement getAccount(), getRefreshToken()
37 |
38 | utils.inherits(AccessToken, require('./InstanceResource'));
39 |
40 | module.exports = AccessToken;
41 |
42 | /**
43 | * Deletes this resource from the API.
44 | *
45 | * @method AccessToken.delete
46 | *
47 | * @param {Function} callback
48 | * The function to call when the delete operation is complete. Will be called
49 | * with the parameter (err).
50 | */
51 |
--------------------------------------------------------------------------------
/lib/resource/AccountCreationPolicy.js:
--------------------------------------------------------------------------------
1 | var InstanceResource = require('./InstanceResource');
2 | var utils = require('../utils');
3 |
4 | /**
5 | * @class AccountCreationPolicy
6 | *
7 | * @description
8 | * Encapsulates the account creation policy of a {@link Directory}. For full documentation of the this resource, please see
9 | * [REST API Reference: Account Creation Policy](https://docs.stormpath.com/rest/product-guide/latest/reference.html#account-creation-policy).
10 | *
11 | * For a high-level overview account verification workflows, please see:
12 | * - [How to Verify an Account’s Email](https://docs.stormpath.com/rest/product-guide/latest/accnt_mgmt.html#how-to-verify-an-account-s-email).
13 | * - [Customizing Stormpath Emails via REST](https://docs.stormpath.com/rest/product-guide/latest/accnt_mgmt.html#customizing-stormpath-emails-via-rest).
14 | *
15 | * This class should not be manually constructed. It should be obtained from one of these methods:
16 | * - {@link Directory#getAccountCreationPolicy Directory.getAccountCreationPolicy()}
17 | *
18 | * @param {Object} accountCreationPolicyResource
19 | * The JSON representation of this resource, retrieved the Stormpath REST API.
20 | */
21 |
22 | /**
23 | * @method AccountCreationPolicy.save
24 | *
25 | * @description
26 | *
27 | * Save changes to this resource.
28 | *
29 | * @param {Function} callback
30 | * The function to call when the save operation is complete. Will be called
31 | * with the parameters (err, updatedResource).
32 | */
33 |
34 |
35 | function AccountCreationPolicy() {
36 | AccountCreationPolicy.super_.apply(this, arguments);
37 | }
38 |
39 | utils.inherits(AccountCreationPolicy, InstanceResource);
40 |
41 | module.exports = AccountCreationPolicy;
--------------------------------------------------------------------------------
/lib/resource/AccountLink.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class AccountLink
8 | *
9 | * @description
10 | *
11 | * Encapsulates an AccountLink resource. For full documentation of this resource,
12 | * please see
13 | * [REST API Reference: AccountLink](https://docs.stormpath.com/rest/product-guide/latest/reference.html#account-link).
14 | *
15 | * For information about automatically generating account links, please see
16 | * {@link https://docs.stormpath.com/rest/product-guide/latest/accnt_mgmt.html#account-linking-automatic Automatic Account Linking}.
17 | *
18 | * This class should not be manually constructed. It should be obtained from one
19 | * of these methods:
20 | *
21 | * - {@link Account#getAccountLinks Account.getAccountLinks()}
22 | * - {@link Account#createAccountLink Account.createAccountLink()}
23 | * - {@link Tenant#createAccountLink Tenant.createAccountLink()}
24 | *
25 | * @augments {InstanceResource}
26 | *
27 | * @param {Object} accountLinkResource
28 | *
29 | * The JSON representation of this resource.
30 | */
31 | function AccountLink() {
32 | AccountLink.super_.apply(this, arguments);
33 | }
34 |
35 | utils.inherits(AccountLink, InstanceResource);
36 |
37 | /**
38 | * Retrieves the "left" account of this account link. The "left" and "right"
39 | * designations are purely arbitrary and imply no hierarchy or priority between
40 | * the two.
41 | *
42 | * @param {ExpansionOptions} [options]
43 | * For retrieving linked resources of the query result.
44 | *
45 | * @param {Function} callback
46 | * The function to call when the operation is complete. Will be called with
47 | * the parameters (err, {@link Account}).
48 | */
49 | AccountLink.prototype.getLeftAccount = function getLeftAccount(/* [options], callback */) {
50 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
51 |
52 | return this.dataStore.getResource(this.leftAccount.href, args.options, require('./Account'), args.callback);
53 | };
54 |
55 | /**
56 | * Retrieves the "right" account of this account link. The "left" and "right"
57 | * designations are purely arbitrary and imply no hierarchy or priority between
58 | * the two.
59 | *
60 | * @param {ExpansionOptions} [options]
61 | * For retrieving linked resources of the query result.
62 | *
63 | * @param {Function} callback
64 | * The function to call when the operation is complete. Will be called with
65 | * the parameters (err, {@link Account}).
66 | */
67 | AccountLink.prototype.getRightAccount = function getRightAccount(/* [options], callback */) {
68 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
69 |
70 | return this.dataStore.getResource(this.rightAccount.href, args.options, require('./Account'), args.callback);
71 | };
72 |
73 | module.exports = AccountLink;
74 |
--------------------------------------------------------------------------------
/lib/resource/AccountLinkingPolicy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class AccountLinkingPolicy
8 | *
9 | * @description
10 | *
11 | * Encapsulates an AccountLinkingPolicy resource. For full documentation of this resource,
12 | * please see
13 | * [REST API Reference: Account LinkingPolicy](https://docs.stormpath.com/rest/product-guide/latest/reference.html#account-linking-policy).
14 | *
15 | * This class should not be manually constructed. It should be obtained from one
16 | * of these methods:
17 | *
18 | * - {@link Application#getAccountLinkingPolicy Application.getAccountLinkingPolicy()}
19 | * - {@link Organization#getAccountLinkingPolicy Organization.getAccountLinkingPolicy()}
20 | *
21 | * Furthermore, an Account Linking Policy cannot be created or deleted from the SDK. Instead, it is
22 | * automatically created for all {@link Application} and {@link Organization} resources,
23 | * but can then be modified.
24 | *
25 | * @augments {InstanceResource}
26 | *
27 | * @param {Object} AccountLinkingPolicyResource
28 | *
29 | * The JSON representation of this resource.
30 | *
31 | */
32 | function AccountLinkingPolicy() {
33 | AccountLinkingPolicy.super_.apply(this, arguments);
34 | }
35 |
36 | utils.inherits(AccountLinkingPolicy, InstanceResource);
37 |
38 | /**
39 | * Retrieves this account linking policy's associated tenant.
40 | *
41 | * @param {ExpansionOptions} options
42 | * Options for retrieving linked resources of the {@link Tenant} during this request.
43 | *
44 | * @param {Function} callback
45 | * The callback that will be called with the parameters (err, {@link Tenant}).
46 | */
47 | AccountLinkingPolicy.prototype.getTenant = function getTenant(/* [options,] callback */) {
48 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
49 |
50 | return this.dataStore.getResource(this.tenant.href, args.options, require('./Tenant'), args.callback);
51 | };
52 |
53 | // Removes the inherited delete method. This resource cannot be deleted manually!
54 | AccountLinkingPolicy.prototype.delete = undefined;
55 |
56 | module.exports = AccountLinkingPolicy;
57 |
--------------------------------------------------------------------------------
/lib/resource/ApplicationAccountStoreMapping.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var AccountStoreMapping = require('./AccountStoreMapping');
5 |
6 | /**
7 | * @class
8 | *
9 | * @augments {AccountStoreMapping}
10 | *
11 | * @description
12 | *
13 | * This object encapsulates an Application Account Store Mapping, which
14 | * represents the link between an {@link Application} and an Account Store, such
15 | * as a {@link Directory}, {@link Group}, or {@link Organization}. For full
16 | * documentation of this resource, please see
17 | * [REST API Reference: Account Store Mapping](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#account-store-mapping).
18 | *
19 | * This class should not be manually constructed. It should be obtained from one
20 | * of these methods:
21 | *
22 | * - {@link Application#createAccountStoreMapping Application.createAccountStoreMapping()}
23 | * - {@link Application#getAccountStoreMappings Application.getAccountStoreMappings()}
24 | *
25 | * For more information about account store mappings, please see
26 | * [Modeling Your User Base](https://docs.stormpath.com/rest/product-guide/latest/accnt_mgmt.html#modeling-your-user-base).
27 | *
28 | * @param {object} accountStoreMappingResource
29 | *
30 | * The JSON representation of this resource.
31 | */
32 | function ApplicationAccountStoreMapping() {
33 | ApplicationAccountStoreMapping.super_.apply(this, arguments);
34 | }
35 |
36 | utils.inherits(ApplicationAccountStoreMapping, AccountStoreMapping);
37 |
38 | /**
39 | * @description
40 | *
41 | * Gets the {@link Application} that is associated with this account store mapping.
42 | *
43 | * @param {ExpansionOptions} [expansionOptions]
44 | * For retrieving linked resources of the {@link Application} during this request.
45 | *
46 | * @param {Function} callback
47 | * The callback to call when the operation is complete. Will be called with
48 | * (err, {@link Application}).
49 | */
50 | ApplicationAccountStoreMapping.prototype.getApplication = function getApplication(/* [options,] callback */) {
51 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
52 | return this.dataStore.getResource(this.application.href, args.options, require('./Application'), args.callback);
53 | };
54 |
55 | /**
56 | * This is not necessary, application can be passed to createAccountStoreMapping(). Remove in 1.0
57 | *
58 | * @private
59 | */
60 | ApplicationAccountStoreMapping.prototype.setApplication = function setApplication(application) {
61 | this.application = { href: application.href };
62 | return this;
63 | };
64 |
65 | module.exports = ApplicationAccountStoreMapping;
66 |
--------------------------------------------------------------------------------
/lib/resource/DirectoryChildResource.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class DirectoryChildResource
8 | */
9 | function DirectoryChildResource() {
10 | DirectoryChildResource.super_.apply(this, arguments);
11 | }
12 | utils.inherits(DirectoryChildResource, InstanceResource);
13 |
14 | /**
15 | * Creates a group membership for a specific account.
16 | *
17 | * @private
18 | *
19 | * @param {Account|Object} account
20 | * An existing instance of {@link Account}, or an object literal with
21 | * an `href` property that identifies the account to add.
22 | *
23 | * @param {Group|Object} group
24 | * An existing instance of the group to create membership in, or an object literal with
25 | * an `href` property that identifies the group to use.
26 | *
27 | * @param {Object} options
28 | * Group membership options.
29 | *
30 | * @param {Function} callback
31 | * The function to call when the operation is complete. Will be called with the
32 | * parameters (err, {@link GroupMembership}).
33 | */
34 | DirectoryChildResource.prototype._createGroupMembership = function createGroupMembership(account, group, options, callback) {
35 | var href = '/groupMemberships';
36 |
37 | var membership = {
38 | account: {
39 | href: account.href
40 | },
41 | group: {
42 | href: group.href
43 | }
44 | };
45 |
46 | return this.dataStore.createResource(href, options, membership, require('./GroupMembership'), callback);
47 | };
48 |
49 | /**
50 | * Gets the directory resource that is a parent of resource.
51 | *
52 | * @param {ExpansionOptions} [expansionOptions]
53 | * For retrieving linked resources of the {@link Directory} during this request.
54 | *
55 | * @param {Function} callback
56 | * The callback that will be called with the parameters (err, {@link Directory}).
57 | */
58 | DirectoryChildResource.prototype.getDirectory = function getDirectoryChildResourceDirectory(/* [options,] callback */) {
59 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
60 | return this.dataStore.getResource(this.directory.href, args.options, require('./Directory'), args.callback);
61 | };
62 |
63 | /**
64 | * Gets the Stormpath tenant resource that owns this resource.
65 | *
66 | * @param {ExpansionOptions} [expansionOptions]
67 | * For retrieving linked resources of the {@link Tenant} during this request.
68 | *
69 | * @param {Function} callback
70 | * The callback that will be called with the parameters (err, {@link Tenant}).
71 | */
72 | DirectoryChildResource.prototype.getTenant = function getDirectoryChildResourceTenant(/* [options,] callback */) {
73 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
74 | return this.dataStore.getResource(this.tenant.href, args.options, require('./Tenant'), args.callback);
75 | };
76 |
77 | /**
78 | * Gets the {@link CustomData} object for this resource.
79 | *
80 | * @param {Function} callback
81 | * The callback that will be called with the parameters (err, {@link CustomData}).
82 | */
83 | DirectoryChildResource.prototype.getCustomData = function getCustomData(/* [options,] callback */) {
84 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
85 | return this.dataStore.getResource(this.customData.href, args.options, require('./CustomData'), args.callback);
86 | };
87 |
88 | module.exports = DirectoryChildResource;
89 |
--------------------------------------------------------------------------------
/lib/resource/Factor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class Factor
8 | *
9 | * @description
10 | *
11 | * Encapsulates a Factor resource, used for purposes of Multi-Factor Authentication.
12 | * For full documentation of this resource,
13 | * please see
14 | * [REST API Reference: Factor](https://docs.stormpath.com/rest/product-guide/latest/reference.html#ref-factor).
15 | *
16 | * This class should not be manually constructed. It should be obtained from one
17 | * of these methods:
18 | *
19 | * - {@link Account#createFactor Account.createFactor()}
20 | * - {@link Account#getFactors Account.getFactors()}
21 | * - {@link Challenge#getFactor Challenge.getFactor()}
22 | * - {@link Client#getFactor Client.getFactor()}
23 | *
24 | * Additionally, raw instances of Factor should never be used. Instead, it is extended
25 | * by concrete {@link SmsFactor} or {@link GoogleAuthenticatorFactor} resources, which
26 | * should be used instead, and will be passed to all callbacks.
27 | *
28 | * @augments {InstanceResource}
29 | *
30 | * @param {Object} factorResource
31 | *
32 | * The JSON representation of this resource.
33 | */
34 | function Factor() {
35 | Factor.super_.apply(this, arguments);
36 | }
37 |
38 | utils.inherits(Factor, InstanceResource);
39 |
40 | /**
41 | * Retrieves the {@link Account} this factor belongs to.
42 | *
43 | * @param {ExpansionOptions} [expansionOptions]
44 | * For retrieving linked resources of the {@link Account} for this request.
45 | * This resource supports expansions for `customData`, `tenant`, `directory`,
46 | * `groups`, and `groupMemberships`. Groups and group memberships can also be
47 | * expanded and paginated.
48 | *
49 | * @param {Function} callback
50 | * The function to call when the operation is complete. Will be called with
51 | * (err, {@link Account}).
52 | */
53 | Factor.prototype.getAccount = function getFactorAccount(/* [options,] callback */) {
54 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
55 | return this.dataStore.getResource(this.account.href, args.options, require('./Account'), args.callback);
56 | };
57 |
58 | /**
59 | * Retrieves a list of challenges for this factor.
60 | *
61 | * @param {CollectionQueryOptions} options
62 | * Options for querying, filtering, sorting, paginating and expanding the query. It can be expanded
63 | * on `account` and `factor` fields.
64 | *
65 | * @param {Function} callback
66 | * The function to call when the operation is complete. Will be called
67 | * with the parameters (err, {@link CollectionResource}). The collection will
68 | * be a list of {@link Challenge} objects.
69 | *
70 | */
71 | Factor.prototype.getChallenges = function getFactorChallenges(/* [options], callback */) {
72 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
73 | return this.dataStore.getResource(this.challenges.href, args.options, require('./Challenge'), args.callback);
74 | };
75 |
76 | /**
77 | * Retrieves the most recent challenge for this factor, or null if none is defined.
78 | *
79 | * @param {ExpansionOptions} [expansionOptions]
80 | * For retrieving linked resources of the {@link Challenge} during this request.
81 | *
82 | * @param {Function} callback
83 | * The function to call when the operation is complete. Will be called with the
84 | * parameters (err, {@link Challenge}), or (err, null) if there is no most recent
85 | * challenge available.
86 | */
87 | Factor.prototype.getMostRecentChallenge = function getMostRecentChallenge(/* [options], callback */) {
88 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
89 |
90 | if (!this.mostRecentChallenge || !this.mostRecentChallenge.href) {
91 | return process.nextTick(args.callback.bind(null, null, null));
92 | }
93 |
94 | return this.dataStore.getResource(this.mostRecentChallenge.href, args.options, require('./Challenge'), args.callback);
95 | };
96 |
97 | module.exports = Factor;
98 |
--------------------------------------------------------------------------------
/lib/resource/FactorInstantiator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var Factor = require('./Factor');
5 | var SmsFactor = require('./SmsFactor');
6 | var GoogleAuthenticatorFactor = require('./GoogleAuthenticatorFactor');
7 | var InstanceResource = require('./InstanceResource');
8 |
9 | /**
10 | * Retrieves the constructor for a correct {@link Factor} instance ({@link SmsFactor} or
11 | * {@link GoogleAuthenticatorFactor}) for corresponding JSON data for the factor.
12 | *
13 | * @private
14 | *
15 | * @param {FactorData} factor
16 | * The data for the factor object
17 | *
18 | * @throws Error If the type is not defined or if it is not a valid type (SMS or google-authenticator)
19 | */
20 | function getFactorConstructor(/* factor */) {
21 | var data = arguments[0];
22 |
23 | if (!data || (typeof data.type === 'undefined')) {
24 | throw new Error('Factor instances must have a defined type');
25 | }
26 |
27 | var type = data.type.toLowerCase();
28 |
29 | switch (type) {
30 | case 'sms':
31 | return SmsFactor;
32 | case 'google-authenticator':
33 | return GoogleAuthenticatorFactor;
34 | default:
35 | return Factor;
36 | }
37 | }
38 |
39 | /**
40 | * @private
41 | *
42 | * @class FactorInstantiator
43 | *
44 | * @description
45 | * The constructor for {@link Factor} instances ({@link SmsFactor} or
46 | * {@link GoogleAuthenticatorFactor}). It parses the data to construct the
47 | * correct constructor, and calls it with the data. It is used for polymorphic
48 | * factor instantiation. It augments {@link InstanceResource} to adhere to the
49 | * interface used for instantiation in {@link ResourceFactory}.
50 | *
51 | * @augments InstanceResource
52 | */
53 | function FactorInstantiator() {
54 | var Ctor = getFactorConstructor.apply(this, arguments);
55 | var argsWithContext = Array.prototype.slice.call(arguments);
56 |
57 | // Adds an initial parameter. It will be the function context (this)
58 | // for the bind call. It does not matter because `new` overwrites, it,
59 | // however, so we're just setting it to null here for syntactic reasons.
60 | argsWithContext.unshift(null);
61 |
62 | return new (Ctor.bind.apply(Ctor, argsWithContext))();
63 | }
64 |
65 | utils.inherits(FactorInstantiator, InstanceResource);
66 |
67 | module.exports = {
68 | Constructor: FactorInstantiator,
69 | getConstructor: getFactorConstructor
70 | };
71 |
--------------------------------------------------------------------------------
/lib/resource/Field.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Resource = require('./Resource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class Field
8 | *
9 | * @description
10 | * Encapsulates an account field, as part of a {@link Schema}.
11 | *
12 | * This class should not be manually constructed. It should be obtained from one of these methods:
13 | *
14 | * - {@link Schema#getFields Schema.getFields()}.
15 | */
16 | function Field(){
17 | Field.super_.apply(this, arguments);
18 | }
19 |
20 | utils.inherits(Field, Resource);
21 |
22 | /**
23 | * Save changes to this resource.
24 | *
25 | * @param {Function} callback
26 | * The function to call when the save operation is complete. Will be called
27 | * with the parameters (err, updatedResource).
28 | */
29 | Field.prototype.save = function save(callback) {
30 | this.dataStore.saveResource(this, callback);
31 | };
32 |
33 | module.exports = Field;
--------------------------------------------------------------------------------
/lib/resource/GoogleAuthenticatorFactor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Factor = require('./Factor');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class GoogleAuthenticatorFactor
8 | *
9 | * @description
10 | *
11 | * Encapsulates a Factor resource, used for purposes of Multi-Factor Authentication.
12 | * This type of Factor uses Google Authenticator as a multi-factor authentication method.
13 | * For full documentation of this resource,
14 | * please see
15 | * [REST API Reference: Creating a Factor](https://docs.stormpath.com/rest/product-guide/latest/reference.html#creating-a-factor).
16 | *
17 | * This class should not be manually constructed. It should be obtained from one
18 | * of these methods:
19 | *
20 | * - {@link Account#createFactor Account.createFactor()}
21 | * - {@link Account#getFactors Account.getFactors()}
22 | * - {@link Challenge#getFactor Challenge.getFactor()}
23 | * - {@link Client#getFactor Client.getFactor()}
24 | *
25 | * @augments {Factor}
26 | *
27 | * @param {Object} factorResource
28 | *
29 | * The JSON representation of this resource.
30 | */
31 | function GoogleAuthenticatorFactor() {
32 | GoogleAuthenticatorFactor.super_.apply(this, arguments);
33 | }
34 |
35 | utils.inherits(GoogleAuthenticatorFactor, Factor);
36 |
37 | /**
38 | * Create a {@link Challenge} resource for this factor. The new challenge resource
39 | * will have a status of `CREATED`. Once the user provides a code from their Google
40 | * Authenticator application, you will verify it with `challenge.verifyCode()`
41 | *
42 | * @param {Object} [requestOptions]
43 | * Query parameters for this request. These can be any of the {@link ExpansionOptions},
44 | * e.g. to retrieve linked resources of the new {@link Challenge} during this request.
45 | *
46 | * @param {Function} callback
47 | * The function to call when the operation is complete. Will be called with the
48 | * parameters (err, {@link Challenge}).
49 | *
50 | * @example
51 | *
52 | * googleAuthenticatorFactor.createChallenge(function(err, createdChallenge) {
53 | * if (err) {
54 | * return console.log(err)
55 | * }
56 | *
57 | * console.log(createdChallenge);
58 | * });
59 | */
60 | GoogleAuthenticatorFactor.prototype.createChallenge = function createFactorChallenge(/* callback */) {
61 | var args = utils.resolveArgs(arguments, ['options','callback'], true);
62 | return this.dataStore.createResource(this.challenges.href, args.options, null, require('./Challenge'), args.callback);
63 | };
64 |
65 | module.exports = GoogleAuthenticatorFactor;
66 |
--------------------------------------------------------------------------------
/lib/resource/GroupMembership.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class GroupMembership
8 | *
9 | * @description
10 | * Encapsulates a GroupMembership resource. For full documentation of this resource, please see
11 | * [REST API Reference: Group Membership](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#group-membership).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link Account#getGroupMemberships Account.getGroupMemberships()}
15 | *
16 | * To remove the group membership, call the `delete()` method on an instance of this class.
17 | *
18 | * @augments {InstanceResource}
19 | *
20 | * @param {Object} groupMembershipResource
21 | * The JSON representation of this resource, retrieved the Stormpath REST API.
22 | */
23 | function GroupMembership() {
24 | GroupMembership.super_.apply(this, arguments);
25 | }
26 | utils.inherits(GroupMembership, InstanceResource);
27 |
28 | /**
29 | * Retrieves the {@link Account account} resource of this membership.
30 | *
31 | * @param {ExpansionOptions} [options]
32 | * For retrieving linked resources of the {@link Account} during this request.
33 | *
34 | * @param {Function} Callback
35 | * Callback function, will be called with (err, {@link Account account}).
36 | */
37 | GroupMembership.prototype.getAccount = function getGroupMembershipAccount(/* [options,] callback */) {
38 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
39 | return this.dataStore.getResource(this.account.href, args.options, require('./Account'), args.callback);
40 | };
41 |
42 | /**
43 | * Retrieves the {@link Group group} resource of this membership.
44 | *
45 | * @param {ExpansionOptions} [options]
46 | * For retrieving linked resources of the {@link Group group} during this request.
47 | *
48 | * @param {Function} Callback
49 | * Callback function, will be called with (err, {@link Group group}).
50 | */
51 | GroupMembership.prototype.getGroup = function getGroupMembershipGroup(/* [options,] callback */) {
52 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
53 | return this.dataStore.getResource(this.group.href, args.options, require('./Group'), args.callback);
54 | };
55 |
56 | module.exports = GroupMembership;
57 |
--------------------------------------------------------------------------------
/lib/resource/IdSiteModel.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class IdSiteModel
8 | *
9 | * @description
10 | * Encapsulates a IdSiteModel resource. For full documentation of this resource, please see
11 | * [REST API Reference: ID Site](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#id-site).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link Organization#getIdSiteModel Organization.getIdSiteModel()}
15 | * - {@link Tenant#getIdSites Tenant.getIdSites()}
16 | *
17 | * @augments {InstanceResource}
18 | *
19 | * @param {Object} idSiteModelResource
20 | * The JSON representation of this resource, retrieved the Stormpath REST API.
21 | */
22 | function IdSiteModel() {
23 | IdSiteModel.super_.apply(this, arguments);
24 | }
25 |
26 | utils.inherits(IdSiteModel, InstanceResource);
27 |
28 | module.exports = IdSiteModel;
29 |
--------------------------------------------------------------------------------
/lib/resource/OAuthPolicy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class OAuthPolicy
8 | *
9 | * @description
10 | *
11 | * Encapsulates a OAuth Policy resource of an {@link Application}. For full
12 | * documentation of this resource please see
13 | * [REST API Reference: OAuth Policy](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#oauth-policy).
14 | *
15 | * For a high level overview of this feature, please see
16 | * [How Token-Based Authentication Works](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#how-token-based-authentication-works).
17 | *
18 | * This class should not be manually constructed. It should be obtained from one
19 | * of these methods:
20 | *
21 | * - {@link Application#getOAuthPolicy Application.getOAuthPolicy()}
22 | *
23 | * @param {Object} oAuthPolicyResource
24 | *
25 | * The JSON representation of this resource, retrieved the Stormpath REST API.
26 | *
27 | */
28 | function OAuthPolicy() {
29 | OAuthPolicy.super_.apply(this, arguments);
30 | }
31 |
32 | utils.inherits(OAuthPolicy, InstanceResource);
33 |
34 | module.exports = OAuthPolicy;
35 |
36 |
37 | /**
38 | * @method OAuthPolicy.save
39 | *
40 | * @description
41 | *
42 | * Save changes to this resource.
43 | *
44 | * @param {Function} callback
45 | * The function to call when the save operation is complete. Will be called
46 | * with the parameters (err, updatedResource).
47 | */
--------------------------------------------------------------------------------
/lib/resource/OrganizationAccountStoreMapping.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var AccountStoreMapping = require('./AccountStoreMapping');
5 |
6 | /**
7 | * @class
8 | *
9 | * @augments {AccountStoreMapping}
10 | *
11 | * @description
12 | *
13 | * Encapsulates an Organization Account Store Mapping, which represents the link
14 | * between an {@link Organization} and a {@link Directory} or {@link Group}. For
15 | * full documentation of this resource, please see
16 | * [REST API Reference: Account Store Mapping](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#account-store-mapping).
17 | *
18 | * This class should not be manually constructed. It should be obtained from one
19 | * of these methods:
20 | *
21 | * - {@link Directory#getOrganizationMappings Directory.getOrganizationMappings()}.
22 | * - {@link Organization#getAccountStoreMappings Organization.getAccountStoreMappings()}.
23 | *
24 | * @param {object} accountStoreMappingResource
25 | *
26 | * The JSON representation of this resource.
27 | *
28 | */
29 | function OrganizationAccountStoreMapping() {
30 | OrganizationAccountStoreMapping.super_.apply(this, arguments);
31 | }
32 |
33 | utils.inherits(OrganizationAccountStoreMapping, AccountStoreMapping);
34 |
35 | /**
36 | * @description
37 | *
38 | * Gets the {@link Organization} that is associated with this account store mapping.
39 | *
40 | * @param {ExpansionOptions} [expansionOptions]
41 | * For retrieving linked resources of the {@link Organization} during this request.
42 | *
43 | * @param {Function} callback
44 | * The callback to call when the operation is complete. Will be called with
45 | * (err, {@link Organization}).
46 | */
47 | OrganizationAccountStoreMapping.prototype.getOrganization = function getOrganization(/* [options,] callback */) {
48 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
49 | return this.dataStore.getResource(this.organization.href, args.options, require('./Organization'), args.callback);
50 | };
51 |
52 | /**
53 | * This is not necessary, organization can be passed to createAccountStoreMapping(). Remove in 1.0
54 | *
55 | * @private
56 | */
57 | OrganizationAccountStoreMapping.prototype.setOrganization = function setOrganization(organization) {
58 | this.organization = { href: organization.href };
59 | return this;
60 | };
61 |
62 | module.exports = OrganizationAccountStoreMapping;
63 |
--------------------------------------------------------------------------------
/lib/resource/PasswordPolicy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class PasswordPolicy
8 | *
9 | * @description
10 | * Encapsulates a PasswordPolicy resource of a {@link Directory}. For full documentation of this resource, please see
11 | * [REST API Reference: Password Policy](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#password-policy).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link Directory#getPasswordPolicy Directory.getPasswordPolicy()}.
15 | *
16 | * @augments {InstanceResource}
17 | *
18 | * @param {Object} passwordPolicyResource
19 | * The JSON representation of this resource, retrieved the Stormpath REST API.
20 | */
21 | function PasswordPolicy() {
22 | PasswordPolicy.super_.apply(this, arguments);
23 | }
24 |
25 | utils.inherits(PasswordPolicy, InstanceResource);
26 |
27 | /**
28 | * Get the {@link Strength} resource of this PasswordPolicy resource.
29 | *
30 | * @param {ExpansionOptions} [expansionOptions]
31 | * For retrieving linked resources of the {@link Strength} resource during this request.
32 | *
33 | * @param {Function} callback
34 | * Callback function, will be called with (err, {@link Strength}).
35 | */
36 | PasswordPolicy.prototype.getStrength = function() {
37 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
38 | return this.dataStore.getResource(this.strength.href, args.options, require('./Strength'), args.callback);
39 | };
40 |
41 | module.exports = PasswordPolicy;
42 |
--------------------------------------------------------------------------------
/lib/resource/PasswordResetToken.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class PasswordResetToken
8 | *
9 | * @description
10 | *
11 | * Encapsulates a PasswordResetToken resource. For full documentation of this
12 | * resource, please see
13 | * [REST API Reference: Password Reset Tokens](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#password-reset-tokens).
14 | *
15 | * This class should not be manually constructed. It should be obtained from one
16 | * of these methods:
17 | *
18 | * - {@link Application#sendPasswordResetEmail Application.sendPasswordResetEmail()}.
19 | *
20 | * To revoke a password reset token, call `delete()` on an instance of this class.
21 | *
22 | * @param {Object} passwordResetTokenResource
23 | *
24 | * The JSON representation of this resource.
25 | *
26 | */
27 | function PasswordResetToken() {
28 | PasswordResetToken.super_.apply(this, arguments);
29 | }
30 | utils.inherits(PasswordResetToken, InstanceResource);
31 |
32 | module.exports = PasswordResetToken;
33 |
34 | /**
35 | * @method PasswordResetToken.delete
36 | *
37 | * @description
38 | *
39 | * Deletes this resource from the API.
40 | *
41 | * @param {Function} callback
42 | * The function to call when the delete operation is complete. Will be called
43 | * with the parameter (err).
44 | */
45 |
--------------------------------------------------------------------------------
/lib/resource/Phone.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class Phone
8 | *
9 | * @description
10 | *
11 | * Encapsulates a Phone resource. For full documentation of this resource,
12 | * please see
13 | * [REST API Reference: Phone](https://docs.stormpath.com/rest/product-guide/latest/reference.html#ref-phone).
14 | *
15 | * This class should not be manually constructed. It should be obtained from one
16 | * of these methods:
17 | *
18 | * - {@link SmsFactor#getPhone SmsFactor.getPhone()}
19 | *
20 | * @augments {InstanceResource}
21 | *
22 | * @param {Object} phoneResource
23 | *
24 | * The JSON representation of this resource.
25 | */
26 | function Phone() {
27 | Phone.super_.apply(this, arguments);
28 | }
29 |
30 | utils.inherits(Phone, InstanceResource);
31 |
32 | /**
33 | * Retrieves the {@link Account} this phone belongs to.
34 | *
35 | * @param {ExpansionOptions} [expansionOptions]
36 | * For retrieving linked resources of the {@link Account} for this request.
37 | * This resource supports expansions for `customData`, `tenant`, `directory`,
38 | * `groups`, and `groupMemberships`. Groups and group memberships can also be
39 | * expanded and paginated.
40 | *
41 | * @param {Function} callback
42 | * The function to call when the operation is complete. Will be called with
43 | * (err, {@link Account}).
44 | */
45 | Phone.prototype.getAccount = function getPhoneAccount(/* callback */) {
46 | var args = utils.resolveArgs(arguments, ['callback'], true);
47 | return this.dataStore.getResource(this.account.href, {}, require('./Account'), args.callback);
48 | };
49 |
50 | module.exports = Phone;
51 |
--------------------------------------------------------------------------------
/lib/resource/Provider.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class Provider
8 | *
9 | * @description
10 | * Encapsulates a Provider resource of a {@link Directory}. For full documentation of this resource, please see
11 | * [REST API Reference: Provider](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#provider).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link Directory#getProvider Directory.getProvider()}.
15 | *
16 | * @augments {InstanceResource}
17 | *
18 | * @param {Object} providerResource
19 | * The JSON representation of this resource, retrieved the Stormpath REST API.
20 | */
21 | function Provider() {
22 | Provider.super_.apply(this, arguments);
23 | }
24 |
25 | utils.inherits(Provider, InstanceResource);
26 |
27 | module.exports = Provider;
28 |
--------------------------------------------------------------------------------
/lib/resource/ProviderData.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class ProviderData
8 | *
9 | * @description
10 | * Encapsulates a ProviderData resource of a {@link Account}. For full documentation of this resource, please see
11 | * [REST API Reference: ProviderData](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#provider-data).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link Account#getProviderData Account.getProviderData()}.
15 | *
16 | * @augments {InstanceResource}
17 | *
18 | * @param {Object} providerDataResource
19 | * The JSON representation of this resource, retrieved the Stormpath REST API.
20 | */
21 | function ProviderData() {
22 | ProviderData.super_.apply(this, arguments);
23 | }
24 |
25 | utils.inherits(ProviderData, InstanceResource);
26 |
27 | module.exports = ProviderData;
28 |
--------------------------------------------------------------------------------
/lib/resource/RefreshToken.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | /**
6 | * @class RefreshToken
7 | *
8 | * @description
9 | *
10 | * Encapsulates a Stormpath OAuth Refresh Token Resource. For full documentation
11 | * of this resource, please see
12 | * [REST API Reference: Refresh Token](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#password-policy).
13 | * For a high-level overview of token management, please see
14 | * {@link https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#introduction-to-token-based-authentication Introduction to Token-Based Authentication}.
15 | *
16 | * This class should not be manually constructed. It should be obtained from one
17 | * of these methods:
18 | *
19 | * - {@link Client#getRefreshToken Client.getRefreshToken()}
20 | * - {@link Account#getRefreshTokens Account.getRefreshTokens()}
21 | *
22 | * To revoke a refresh token, invoke the `delete()` method on an instance of
23 | * this class.
24 | *
25 | * @param {Object} refreshTokenResource
26 | *
27 | * The JSON representation of this resource, retrieved the Stormpath REST API.
28 | */
29 | function RefreshToken() {
30 | RefreshToken.super_.apply(this, arguments);
31 | }
32 |
33 | utils.inherits(RefreshToken, require('./InstanceResource'));
34 |
35 | module.exports = RefreshToken;
36 |
37 | /**
38 | * Deletes this resource from the API.
39 | *
40 | * @method RefreshToken.delete
41 | *
42 | * @param {Function} callback
43 | * The function to call when the delete operation is complete. Will be called
44 | * with the parameter (err).
45 | */
46 |
47 |
--------------------------------------------------------------------------------
/lib/resource/Resource.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 |
5 | function Resource(data, dataStore) {
6 | // require moved here intentionally because of
7 | // issue related to
8 | var DataStore = require('../ds/DataStore');
9 | if (!dataStore && data instanceof DataStore){
10 | dataStore = data;
11 | data = null;
12 | }
13 | data = data || {};
14 |
15 | for (var key in data) {
16 | if (data.hasOwnProperty(key)) {
17 | this[key] = data[key];
18 | }
19 | }
20 |
21 | var ds = null; //private var, not enumerable
22 | Object.defineProperty(this, 'dataStore', {
23 | get: function getDataStore() {
24 | return ds;
25 | },
26 | set: function setDataStore(dataStore) {
27 | ds = dataStore;
28 | }
29 | });
30 | if (dataStore) {
31 | this.dataStore = dataStore;
32 | }
33 | }
34 | utils.inherits(Resource, Object);
35 |
36 | module.exports = Resource;
--------------------------------------------------------------------------------
/lib/resource/SamlAttributeStatementMappingRules.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class SamlAttributeStatementMappingRules
8 | *
9 | * @description
10 | *
11 | * Encapsulates a AttributeStatementMappingRules resource.
12 | * For more information about this resource, please see:
13 | * [REST API Reference: Configure SAML Attribute Mapping](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#step-7-configure-saml-attribute-mapping-optional).
14 | *
15 | * For a high-level overview of SAML Authentication, please see
16 | * [Authenticating Against a SAML Directory](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#authenticating-against-a-saml-directory).
17 | *
18 | * For more information about configuring SAML Authentication, please see
19 | * [Configuring SAML via REST](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#configuring-saml-via-rest).
20 | *
21 | * This class should not be manually constructed. It should be obtained from one
22 | * of these methods:
23 | *
24 | * - {@link SamlProvider#getAttributeStatementMappingRules SamlProvider.getAttributeStatementMappingRules()}
25 | *
26 | * @param {Object} attributeStatementMappingRules
27 | *
28 | * The JSON representation of this resource, retrieved the Stormpath REST API.
29 | *
30 | */
31 | function SamlAttributeStatementMappingRules() {
32 | SamlAttributeStatementMappingRules.super_.apply(this, arguments);
33 | }
34 |
35 | utils.inherits(SamlAttributeStatementMappingRules, InstanceResource);
36 |
37 | module.exports = SamlAttributeStatementMappingRules;
38 |
39 | /**
40 | * @method SamlAttributeStatementMappingRules.save
41 | *
42 | * @description
43 | *
44 | * Save changes to this resource.
45 | *
46 | * @param {Function} callback
47 | * The function to call when the save operation is complete. Will be called
48 | * with the parameters (err, updatedResource).
49 | */
--------------------------------------------------------------------------------
/lib/resource/SamlPolicy.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class SamlPolicy
8 | *
9 | * @description
10 | *
11 | * Encapsulates the SAML Policy of an {@link Application}. For full documentation
12 | * of the this resource, please see
13 | * [REST API Reference: SAML Policy Resource](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#saml-policy-resource).
14 | *
15 | * For a high-level overview of SAML Authentication, please see
16 | * [Authenticating Against a SAML Directory](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#authenticating-against-a-saml-directory).
17 | *
18 | * For more information about configuring SAML Authentication, please see
19 | * [Configuring SAML via REST](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#configuring-saml-via-rest).
20 | *
21 | * This class should not be manually constructed. It should be obtained from one
22 | * of these methods:
23 | *
24 | * - {@link Application#getSamlPolicy Application.getSamlPolicy()}
25 | *
26 | * @param {Object} samlPolicyResource
27 | * The JSON representation of this resource, retrieved the Stormpath REST API.
28 | *
29 | */
30 | function SamlPolicy() {
31 | SamlPolicy.super_.apply(this, arguments);
32 | }
33 |
34 | utils.inherits(SamlPolicy, InstanceResource);
35 |
36 | /**
37 | * Get the {@link SamlServiceProvider} resource of this SAML Policy resource.
38 | *
39 | * @param {ExpansionOptions} [expansionOptions]
40 | * For retrieving linked resources of the {@link SamlServiceProvider} resource during this request.
41 | *
42 | * @param {Function} callback
43 | * Callback function, will be called with (err, {@link SamlServiceProvider samlServiceProvider}).
44 | */
45 | SamlPolicy.prototype.getServiceProvider = function getServiceProvider(/* [options,] callback */) {
46 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
47 | return this.dataStore.getResource(this.serviceProvider.href, args.options, require('./SamlServiceProvider'), args.callback);
48 | };
49 |
50 | module.exports = SamlPolicy;
51 |
--------------------------------------------------------------------------------
/lib/resource/SamlProvider.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class SamlProvider
8 | *
9 | * @description
10 | *
11 | * Encapsulates a SamlProvider resource, which is a type of {@link Provider}.
12 | * For full documentation of the Provider resource, please see
13 | * [REST API Reference: Provider](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#provider).
14 | *
15 | * For a high-level overview of SAML Authentication, please see
16 | * [Authenticating Against a SAML Directory](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#authenticating-against-a-saml-directory).
17 | *
18 | * For more information about configuring SAML Authentication, please see
19 | * [Configuring SAML via REST](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#configuring-saml-via-rest).
20 | *
21 | * This class should not be manually constructed. It should be obtained from one
22 | * of these methods:
23 | *
24 | * - {@link Directory#getProvider Directory.getProvider()}
25 | *
26 | * @augments {InstanceResource}
27 | *
28 | * @param {Object} samlProviderResource
29 | *
30 | * The JSON representation of this resource, retrieved the Stormpath REST API.
31 | *
32 | */
33 | function SamlProvider() {
34 | SamlProvider.super_.apply(this, arguments);
35 | }
36 |
37 | utils.inherits(SamlProvider, InstanceResource);
38 |
39 | /**
40 | * Get the {@link SamlAttributeStatementMappingRules} resource of this SamlProvider resouce.
41 | *
42 | * @param {ExpansionOptions} [expansionOptions]
43 | * For retrieving linked resources of the {@link SamlAttributeStatementMappingRules} resource during this request.
44 | *
45 | * @param {Function} callback
46 | * Callback function, will be called with (err, {@link SamlAttributeStatementMappingRules samlServiceProviderMetadata}).
47 | */
48 | SamlProvider.prototype.getAttributeStatementMappingRules = function getAttributeStatementMappingRules(/* [options,] callback */) {
49 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
50 | return this.dataStore.getResource(this.attributeStatementMappingRules.href, args.options, require('./SamlAttributeStatementMappingRules'), args.callback);
51 | };
52 |
53 | /**
54 | * Get the {@link SamlServiceProviderMetadata} resource of this SamlProvider resouce.
55 | *
56 | * @param {ExpansionOptions} [expansionOptions]
57 | * For retrieving linked resources of the {@link SamlServiceProviderMetadata} resource during this request.
58 | *
59 | * @param {Function} callback
60 | * Callback function, will be called with (err, {@link SamlServiceProviderMetadata samlServiceProviderMetadata}).
61 | */
62 | SamlProvider.prototype.getServiceProviderMetadata = function getServiceProviderMetadata(/* [options,] callback */) {
63 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
64 | return this.dataStore.getResource(this.serviceProviderMetadata.href, args.options, require('./SamlServiceProviderMetadata'), args.callback);
65 | };
66 |
67 | module.exports = SamlProvider;
68 |
--------------------------------------------------------------------------------
/lib/resource/SamlServiceProvider.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class SamlServiceProvider
8 | *
9 | * @description
10 | *
11 | * Encapsulates the SAML Service Provider of an {@link Application}. For full
12 | * documentation of this resource, please see
13 | * [REST API Reference: SAML Policy Resource](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#saml-policy-resource).
14 | *
15 | * For a high-level overview of SAML Authentication, please see
16 | * [Authenticating Against a SAML Directory](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#authenticating-against-a-saml-directory).
17 | *
18 | * For more information about configuring SAML Authentication, please see
19 | * [Configuring SAML via REST](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#configuring-saml-via-rest).
20 | *
21 | * This class should not be manually constructed. It should be obtained from one
22 | * of these methods:
23 | *
24 | * - {@link SamlPolicy#getServiceProvider SamlPolicy.getServiceProvider()}
25 | *
26 | * @param {Object} samlServiceProviderResource
27 | *
28 | * The JSON representation of this resource, retrieved the Stormpath REST API.
29 | */
30 | function SamlServiceProvider() {
31 | SamlServiceProvider.super_.apply(this, arguments);
32 | }
33 |
34 | utils.inherits(SamlServiceProvider, InstanceResource);
35 |
36 | module.exports = SamlServiceProvider;
37 |
--------------------------------------------------------------------------------
/lib/resource/SamlServiceProviderMetadata.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class SamlServiceProviderMetadata
8 | *
9 | * @description
10 | *
11 | * Encapsulates a SAML Service Provider Metadata Resource. For full
12 | * documentation of this resource, please see
13 | * [Retrieve Your Service Provider Metadata](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#step-3-retrieve-your-service-provider-metadata).
14 | *
15 | * For a high-level overview of SAML Authentication, please see
16 | * [Authenticating Against a SAML Directory](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#authenticating-against-a-saml-directory).
17 | *
18 | * For more information about configuring SAML Authentication, please see
19 | * [Configuring SAML via REST](https://docs.stormpath.com/rest/product-guide/latest/auth_n.html?#configuring-saml-via-rest).
20 | *
21 | * This class should not be manually constructed. It should be obtained from one
22 | * of these methods:
23 | *
24 | * - {@link SamlProvider#getServiceProviderMetadata SamlProvider.getServiceProviderMetadata()}
25 | *
26 | * @param {Object} samlServiceProviderMetadataResource
27 | *
28 | * The JSON representation of this resource, retrieved the Stormpath REST API.
29 | */
30 | function SamlServiceProviderMetadata() {
31 | SamlServiceProviderMetadata.super_.apply(this, arguments);
32 | }
33 |
34 | utils.inherits(SamlServiceProviderMetadata, InstanceResource);
35 |
36 | module.exports = SamlServiceProviderMetadata;
37 |
--------------------------------------------------------------------------------
/lib/resource/Schema.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Resource = require('./Resource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class Schema
8 | *
9 | * @description
10 | * Encapsulates the Schema resource of a {@link Directory}. This schema allows you
11 | * to control which Account attributes (referred to as fields) are required when
12 | * creating new accounts in the directory. For full documentation of this resource, please see
13 | * [How to Manage an Account’s Required Attributes](https://docs.stormpath.com/rest/product-guide/latest/accnt_mgmt.html#how-to-manage-an-account-s-required-attributes).
14 | *
15 | * This class should not be manually constructed. It should be obtained from one of these methods:
16 | * - {@link Directory#getAccountSchema Directory.getAccountSchema()}.
17 | *
18 | * @example Disabling a field requirement.
19 | * var _ = require('lodash');
20 | *
21 | * schema.getFields(function (err, fieldsCollection) {
22 | * var givenNameField = _.find(fieldsCollection.items, {
23 | * name: 'givenName'
24 | * });
25 | *
26 | * givenNameField.required = false;
27 | *
28 | * givenNameField.save();
29 | * });
30 | */
31 | function Schema() {
32 | Schema.super_.apply(this, arguments);
33 | }
34 |
35 | utils.inherits(Schema, Resource);
36 |
37 | /**
38 | * Get the collection of {@link Field Fields} for this schema.
39 | *
40 | * @param {CollectionQueryOptions} [options]
41 | * Options for querying, paginating, and expanding the collection.
42 | *
43 | * @param {Function} callback
44 | * The function to call when the operation is complete. Will be called
45 | * with the parameters (err, {@link CollectionResource}). The collection will
46 | * be a list of {@link Field} objects.
47 | */
48 | Schema.prototype.getFields = function () {
49 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
50 | return this.dataStore.getResource(this.fields.href, args.options, require('./Field'), args.callback);
51 | };
52 |
53 | module.exports = Schema;
--------------------------------------------------------------------------------
/lib/resource/SmsFactor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Factor = require('./Factor');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class SmsFactor
8 | *
9 | * @description
10 | *
11 | * Encapsulates a Factor resource, used for purposes of Multi-Factor Authentication.
12 | * This type of Factor uses SMS as a multi-factor authentication method.
13 | * For full documentation of this resource,
14 | * please see
15 | * [REST API Reference: Creating a Factor](https://docs.stormpath.com/rest/product-guide/latest/reference.html#creating-a-factor).
16 | *
17 | * This class should not be manually constructed. It should be obtained from one
18 | * of these methods:
19 | *
20 | * - {@link Account#createFactor Account.createFactor()}
21 | * - {@link Account#getFactors Account.getFactors()}
22 | * - {@link Challenge#getFactor Challenge.getFactor()}
23 | * - {@link Client#getFactor Client.getFactor()}
24 | *
25 | * @augments {Factor}
26 | *
27 | * @param {Object} factorResource
28 | *
29 | * The JSON representation of this resource.
30 | */
31 | function SmsFactor() {
32 | SmsFactor.super_.apply(this, arguments);
33 | }
34 |
35 | utils.inherits(SmsFactor, Factor);
36 |
37 |
38 | /**
39 | * Create a {@link Challenge} for this factor, which is used to start the multi-factor
40 | * authentication procedure. This will send an SMS message to the user with the
41 | * code. For more information about this process, See
42 | * {@link https://docs.stormpath.com/rest/product-guide/latest/auth_n.html#challenging-an-sms-factor Challenging an SMS Factor}.
43 | *
44 | * @param {Object} [challenge]
45 | * An object literal for configuring the challenge. If this object is not provied,
46 | * a default challenge message will be sent.
47 | *
48 | * @param {String} challenge.message
49 | * The message to be sent to the user.
50 | *
51 | * @param {Object} [requestOptions]
52 | * Query parameters for this request. These can be any of the {@link ExpansionOptions},
53 | * e.g. to retrieve linked resources of the new {@link Challenge} during this request.
54 | *
55 | * @param {Function} callback
56 | * The function to call when the operation is complete. Will be called with the
57 | * parameters (err, {@link Challenge}).
58 | *
59 | * @example
60 | * var challenge = {
61 | * message: 'Your verification code is: ${code}'
62 | * };
63 | *
64 | * smsFactor.createChallenge(challenge, function(err, createdChallenge) {
65 | * if (err) {
66 | * return console.log(err);
67 | * }
68 | * console.log(createdChallenge);
69 | * });
70 | */
71 | SmsFactor.prototype.createChallenge = function createFactorChallenge(/* challenge, [options], callback */) {
72 | var args = utils.resolveArgs(arguments, ['challenge', 'options', 'callback'], true);
73 | return this.dataStore.createResource(this.challenges.href, args.options, args.challenge, require('./Challenge'), args.callback);
74 | };
75 |
76 |
77 | /**
78 | * Retrieves the phone to which the multi-factor authentication SMS is sent to.
79 | *
80 | * @param {ExpansionOptions} [expansionOptions]
81 | * For retrieving linked resources of the {@link Phone} during this request.
82 | *
83 | * @param {Function} callback
84 | * The function to call when the operation is complete. Will be called with the
85 | * parameters (err, {@link Phone}).
86 | */
87 | SmsFactor.prototype.getPhone = function getPhone(/* callback */) {
88 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
89 | return this.dataStore.getResource(this.phone.href, args.options, require('./Phone'), args.callback);
90 | };
91 |
92 | module.exports = SmsFactor;
93 |
--------------------------------------------------------------------------------
/lib/resource/SmtpServer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var utils = require('../utils');
4 | var InstanceResource = require('./InstanceResource');
5 |
6 | /**
7 | * @class SmtpServer
8 | *
9 | * @description
10 | * Encapsulates a SmtpServer resource. For full documentation of this resource, please see
11 | * [REST API Reference: SMTP Server](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#smtp-server).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link Client#getSmtpServers Client.getSmtpServers()}
15 | * - {@link Tenant#getSmtpServers Tenant.getSmtpServers()}
16 | *
17 | * @augments {InstanceResource}
18 | *
19 | * @param {Object} smtpServerResource
20 | * The JSON representation of this resource, retrieved the Stormpath REST API.
21 | */
22 | function SmtpServer() {
23 | SmtpServer.super_.apply(this, arguments);
24 | }
25 |
26 | utils.inherits(SmtpServer, InstanceResource);
27 |
28 | module.exports = SmtpServer;
29 |
--------------------------------------------------------------------------------
/lib/resource/Strength.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var InstanceResource = require('./InstanceResource');
4 | var utils = require('../utils');
5 |
6 | /**
7 | * @class Strength
8 | *
9 | * @description
10 | * Encapsulates a Password Strength resource of a {@link PasswordPolicy}. For full documentation of the this resource, please see
11 | * [REST API Reference: Password Strength](https://docs.stormpath.com/rest/product-guide/latest/reference.html?#password-strength).
12 | *
13 | * This class should not be manually constructed. It should be obtained from one of these methods:
14 | * - {@link PasswordPolicy#getStrength PasswordPolicy.getStrength()}
15 | *
16 | * @augments {InstanceResource}
17 | *
18 | * @param {Object} passwordStrengthResource
19 | * The JSON representation of this resource, retrieved the Stormpath REST API.
20 | */
21 | function Strength() {
22 | Strength.super_.apply(this, arguments);
23 | }
24 |
25 | utils.inherits(Strength, InstanceResource);
26 |
27 | module.exports = Strength;
28 |
--------------------------------------------------------------------------------
/lib/resource/mixins/SaveableMixin.js:
--------------------------------------------------------------------------------
1 | function applyCustomDataUpdatesIfNecessary(cb){
2 | if (!this.customData){
3 | return cb();
4 | }
5 |
6 | if (this.customData._hasReservedFields()){
7 | this.customData = this.customData._deleteReservedFields();
8 | }
9 |
10 | if (this.customData._hasRemovedProperties()){
11 | return this.customData._deleteRemovedProperties(cb);
12 | }
13 |
14 | return cb();
15 | }
16 |
17 | /**
18 | * Save changes to this resource.
19 | *
20 | * @param {Function} callback
21 | * The function to call when the save operation is complete. Will be called
22 | * with the parameters (err, updatedResource).
23 | */
24 | function saveResource(callback) {
25 | var self = this;
26 | self._applyCustomDataUpdatesIfNecessary(function () {
27 | self.dataStore.saveResource(self, callback);
28 | });
29 | }
30 |
31 | var SaveableMixin = {
32 | _applyCustomDataUpdatesIfNecessary: applyCustomDataUpdatesIfNecessary,
33 | save: saveResource
34 | };
35 |
36 | module.exports = SaveableMixin;
37 |
--------------------------------------------------------------------------------
/lib/saml/SamlIdpUrlBuilder.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var njwt = require('njwt');
4 | var uuid = require('uuid');
5 | var querystring = require('querystring');
6 |
7 | var utils = require('../utils');
8 |
9 | /**
10 | * Creates a URL builder that can build SAML IDP redirect URLs. This is done
11 | * when Stormpath is initiating a redirect to a SAML IDP.
12 | * For more information, please see
13 | * [Authenticating Against a SAML Directory](http://docs.stormpath.com/rest/product-guide/latest/auth_n.html#authenticating-against-a-saml-directory).
14 | *
15 | * This authenticator is bound to the application that you pass to the constructor.
16 | *
17 | * @class
18 | *
19 | * @param {Application} application
20 | *
21 | * The Stormpath Application that will issue the redirect. This application must
22 | * be mapped to the relevant SAML Directories.
23 | *
24 | * @example
25 | *
26 | * var builder = new stormpath.SamlIdpUrlBuilder(application);
27 | */
28 | function SamlIdpUrlBuilder(application) {
29 | this.application = application;
30 | this.apiKey = application.dataStore.requestExecutor.options.client.apiKey;
31 | }
32 |
33 | SamlIdpUrlBuilder.prototype._getServiceProvider = function _getServiceProvider(callback) {
34 | this.application.getSamlPolicy(function (err, samlPolicy) {
35 | if (err) {
36 | return callback(err);
37 | }
38 |
39 | samlPolicy.getServiceProvider(callback);
40 | });
41 | };
42 |
43 | SamlIdpUrlBuilder.prototype._buildInitializationUrl = function _buildInitializationUrl(initEndpointUrl, parameters) {
44 | return initEndpointUrl + '?' + querystring.stringify(parameters);
45 | };
46 |
47 | /**
48 | * Builds a SAML IDP Redirect URL and provides it to the specified callback.
49 | *
50 | * @param {Object} options
51 | * Optional claims for the [SAML Authentication JWT](http://docs.stormpath.com/rest/product-guide/latest/auth_n.html#saml-authentication-jwt).
52 | * Use these claims to control the callback url (`cb_url`), token state (`state`),
53 | * and account store target (`ash` or `onk`). The other required claims will be
54 | * set automatically by the builder.
55 | *
56 | * @paarm {Function} callback
57 | * The callback to call with the URL string that was built. Will be called with
58 | * (err, urlString).
59 | *
60 | * @example
61 | * builder.build(function(err, url) {
62 | * if (err) {
63 | * console.error(err);
64 | * return;
65 | * }
66 | * console.log(url);
67 | * });
68 | */
69 | SamlIdpUrlBuilder.prototype.build = function (/* [options,] callback */) {
70 | var self = this;
71 |
72 | var apiKey = this.apiKey;
73 | var args = utils.resolveArgs(arguments, ['options', 'callback'], true);
74 |
75 | this._getServiceProvider(function (err, serviceProvider) {
76 | if (err) {
77 | return args.callback(err);
78 | }
79 |
80 | var claims = {
81 | jti: uuid(),
82 | iss: self.application.href,
83 | iat: new Date().getTime() / 1000
84 | };
85 |
86 | var options = args.options || {};
87 |
88 | if (options.cb_uri) {
89 | claims.cb_uri = options.cb_uri;
90 | }
91 |
92 | if (options.ash) {
93 | claims.ash = options.ash;
94 | }
95 |
96 | if (options.onk) {
97 | claims.onk = options.onk;
98 | }
99 |
100 | if (options.state) {
101 | claims.state = options.state;
102 | }
103 |
104 | var accessToken = njwt.create(claims, apiKey.secret);
105 |
106 | accessToken.header.kid = apiKey.id;
107 |
108 | var parameters = {
109 | accessToken: accessToken.compact()
110 | };
111 |
112 | var ssoInitiationEndpoint = serviceProvider.ssoInitiationEndpoint.href;
113 | var initializationUrl = self._buildInitializationUrl(ssoInitiationEndpoint, parameters);
114 |
115 | args.callback(null, initializationUrl);
116 | });
117 | };
118 |
119 | module.exports = SamlIdpUrlBuilder;
120 |
--------------------------------------------------------------------------------
/lib/stormpath.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var passwordGrant = require('./oauth/password-grant');
4 | var refreshGrant = require('./oauth/refresh-grant');
5 | var idSiteGrant = require('./oauth/id-site-grant');
6 | var stormpathToken = require('./oauth/stormpath-token');
7 | var clientCredentialsGrant = require('./oauth/client-credentials');
8 | var stormpathSocial = require('./oauth/stormpath-social');
9 |
10 | module.exports = {
11 | ApiKey: require('./authc/ApiKey'),
12 | loadApiKey: require('./authc/ApiKeyLoader'),
13 | configLoader: require('./configLoader'),
14 | Client: require('./Client'),
15 | Tenant: require('./resource/Tenant'),
16 | OAuthPasswordGrantRequestAuthenticator: passwordGrant.authenticator,
17 | OauthPasswordGrantAuthenticationResult: passwordGrant.authenticationResult,
18 | OAuthRefreshTokenGrantRequestAuthenticator: refreshGrant.authenticator,
19 | OAuthIdSiteTokenGrantAuthenticator: idSiteGrant.authenticator,
20 | OAuthIdSiteTokenGrantAuthenticationResult: idSiteGrant.authenticationResult,
21 | OAuthStormpathTokenAuthenticator: stormpathToken.authenticator,
22 | OAuthStormpathSocialAuthenticator: stormpathSocial.authenticator,
23 | OAuthStormpathTokenAuthenticationResult: stormpathToken.authenticationResult,
24 | OAuthClientCredentialsAuthenticator: clientCredentialsGrant.authenticator,
25 | OAuthClientCredentialsAuthenticationResult: clientCredentialsGrant.authenticationResult,
26 | SamlIdpUrlBuilder: require('./saml/SamlIdpUrlBuilder'),
27 | AssertionAuthenticationResult: require('./authc/AssertionAuthenticationResult'),
28 | StormpathAccessTokenAuthenticator: require('./oauth/stormpath-access-token-authenticator'),
29 | StormpathAssertionAuthenticator: require('./authc/StormpathAssertionAuthenticator'),
30 | JwtAuthenticator: require('./jwt/jwt-authenticator'),
31 | OAuthAuthenticator: require('./oauth/authenticator')
32 | };
33 |
--------------------------------------------------------------------------------
/lib/underscore.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _ = require('underscore');
4 |
5 | // Import Underscore.string to separate object, because there are conflict functions (include, reverse, contains)
6 | _.str = require('underscore.string');
7 |
8 | // Mix in non-conflict functions to Underscore namespace if you want
9 | _.mixin(_.str.exports());
10 |
11 | // All functions, include conflict, will be available through _.str object
12 | _.str.include('Underscore.string', 'string'); // => true
13 |
14 | module.exports = _;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stormpath",
3 | "version": "0.20.1",
4 | "main": "lib/stormpath.js",
5 | "description": "Official Stormpath SDK for Node.js",
6 | "keywords": [
7 | "stormpath",
8 | "api",
9 | "wrapper",
10 | "sdk",
11 | "client",
12 | "user",
13 | "user management",
14 | "user login",
15 | "identity",
16 | "identity management",
17 | "account",
18 | "account login",
19 | "login",
20 | "authentication",
21 | "authorization",
22 | "access control",
23 | "password",
24 | "password hash"
25 | ],
26 | "license": "Apache-2.0",
27 | "homepage": "https://github.com/stormpath/stormpath-sdk-node",
28 | "bugs": "https://github.com/stormpath/stormpath-sdk-node/issues",
29 | "author": {
30 | "name": "Stormpath, Inc.",
31 | "email": "support@stormpath.com",
32 | "url": "http://www.stormpath.com"
33 | },
34 | "repository": {
35 | "type": "git",
36 | "url": "git://github.com/stormpath/stormpath-sdk-node.git"
37 | },
38 | "scripts": {
39 | "coverage": "node ./node_modules/istanbul/lib/cli cover ./node_modules/mocha/bin/_mocha",
40 | "docs": "./node_modules/.bin/jsdoc -c ./docs/jsdoc.json -d ./apidocs/ -P ./package.json -r lib/ --readme ./docs/JSDOC.md",
41 | "test": "grunt"
42 | },
43 | "dependencies": {
44 | "async": "~1.5.2",
45 | "deep-extend": "^0.4.1",
46 | "jwt-simple": "~0.4.0",
47 | "memcached": "~2.2.2",
48 | "moment": "^2.15.2",
49 | "njwt": "^0.4.0",
50 | "properties-parser": "~0.3.1",
51 | "redis": "~2.6.2",
52 | "request": "~2.74.0",
53 | "stormpath-config": "0.0.27",
54 | "underscore": "~1.5.2",
55 | "underscore.string": "~3.2.3",
56 | "uuid": "^3.0.0",
57 | "xtend": "^4.0.1"
58 | },
59 | "devDependencies": {
60 | "benchmark": "^2.0.0",
61 | "chai": "~3.5.0",
62 | "coveralls": "^2.11.11",
63 | "expand-home-dir": "0.0.3",
64 | "fake-fs": "^0.5.0",
65 | "grunt": "~1.0.1",
66 | "grunt-cli": "~1.2.0",
67 | "grunt-contrib-jshint": "~0.11.3",
68 | "grunt-contrib-watch": "~1.0.0",
69 | "grunt-mocha-istanbul": "~5.0.1",
70 | "grunt-mocha-test": "~0.12.7",
71 | "httpster": "^1.0.3",
72 | "ink-docstrap": "^1.1.4",
73 | "istanbul": "^0.4.4",
74 | "js-yaml": "~3.6.1",
75 | "jsdoc": "^3.4.0",
76 | "jshint-stylish": "~2.2.0",
77 | "load-grunt-tasks": "~3.5.0",
78 | "lodash": "^4.0.1",
79 | "mocha": "~2.5.3",
80 | "mocha-sinon": "~1.1.0",
81 | "nock": "~8.0.0",
82 | "nodemon": "^1.9.1",
83 | "sinon": "~1.17.3",
84 | "sinon-chai": "~2.8.0",
85 | "time-grunt": "~1.4.0",
86 | "timekeeper": "~0.1.1",
87 | "tmp": "0.0.28"
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/test/apikey_test.js:
--------------------------------------------------------------------------------
1 | /*jshint expr: true*/
2 | /*jshint unused: false*/
3 | 'use strict';
4 |
5 | var authc = require('../lib/authc');
6 | var propsParser = require('properties-parser');
7 | var tmp = require('tmp');
8 | var fs = require('fs');
9 | var chai = require('chai');
10 | var should = chai.should();
11 |
12 | chai.use(require('sinon-chai'));
13 | require('mocha-sinon');
14 |
15 | var home = process.env[(process.platform === 'win32' ? 'USERPROFILE' : 'HOME')];
16 | var apiKeyFilePath = home + '/.stormpath/apiKey.properties2';
17 |
18 | describe('ApiKey', function () {
19 | var apiKey;
20 | before(function(done){
21 | tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback) {
22 | if(err){ throw err;}
23 | fs.write(fd, "apiKey.id = 1234\napiKey.secret = abcd");
24 | fs.close(fd, function(err) {
25 | if(err){ throw err;}
26 | authc.loadApiKey(path,function(err,_apiKey){
27 | if(err){ throw err;}
28 | apiKey = _apiKey;
29 | done();
30 | });
31 | });
32 | });
33 | });
34 | it('should have id and secret properties', function () {
35 | apiKey.id.should.equal('1234');
36 | apiKey.secret.should.equal('abcd');
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/test/common.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var _ = require('lodash');
4 | //_.extend(process.env, require('./test.env'));
5 |
6 | var chai = require("chai");
7 | var nock = require('nock');
8 | var sinon = require("sinon");
9 | var assert = require('chai').assert;
10 | var should = require("chai").should();
11 | var moment = require('moment');
12 | var sinonChai = require("sinon-chai");
13 | var uuid = require('uuid');
14 | var nock = require('nock');
15 | var timekeeper = require('timekeeper');
16 | var jwt = require('njwt');
17 |
18 | var Stormpath = require('../lib');
19 | chai.use(sinonChai);
20 |
21 | function u(){}
22 | u.BASE_URL = 'https://api.stormpath.com';
23 | /** adds '/v1' to relative URL, to work with nock request mocker */
24 | u.v1 = function(s){return '/v1' + s;};
25 |
26 | function random(){
27 | return '' + Math.random()*Date.now();
28 | }
29 |
30 | function clone(value) {
31 | return JSON.parse(JSON.stringify(value));
32 | }
33 |
34 | function snapshotEnv() {
35 | var originalEnv = clone(process.env);
36 | return function restore() {
37 | var key;
38 | for (key in process.env) {
39 | if (!(key in originalEnv)) {
40 | delete process.env[key];
41 | }
42 | }
43 | for (key in originalEnv) {
44 | process.env[key] = originalEnv[key];
45 | }
46 | };
47 | }
48 |
49 | function assertAccessTokenResponse(response){
50 | assert.isDefined(response.accessTokenResponse);
51 | assert.isDefined(response.accessTokenResponse.access_token);
52 | assert.isDefined(response.accessTokenResponse.refresh_token);
53 | assert.isDefined(response.accessToken);
54 | assert.isDefined(response.refreshToken);
55 | }
56 |
57 | function assertPasswordGrantResponse(done){
58 | return function(err,response){
59 | assert.isNull(err);
60 | assert.instanceOf(response,Stormpath.OauthPasswordGrantAuthenticationResult);
61 | assertAccessTokenResponse(response);
62 | done();
63 | };
64 | }
65 |
66 | module.exports = {
67 | _: _,
68 | u: u,
69 | chai: chai,
70 | nock: nock,
71 | sinon: sinon,
72 | assert: assert,
73 | expect: chai.expect,
74 | config: process.env,
75 | should: should,
76 | moment: moment,
77 | Stormpath: Stormpath,
78 | timekeeper: timekeeper,
79 | random: random,
80 | uuid: uuid,
81 | jwt: jwt,
82 | snapshotEnv: snapshotEnv,
83 | assertPasswordGrantResponse: assertPasswordGrantResponse,
84 | assertAccessTokenResponse: assertAccessTokenResponse
85 | };
86 |
--------------------------------------------------------------------------------
/test/fixtures/account-token.js:
--------------------------------------------------------------------------------
1 | /*
2 | This fixture creates a new application, directory,
3 | and account. It issues an Oauth request for the
4 | account, resulting in an access token and refresh
5 | token in the token collections for the account
6 | */
7 |
8 | var helpers = require('../it/helpers');
9 | var OAuthPasswordGrantRequestAuthenticator = require('../../').OAuthPasswordGrantRequestAuthenticator;
10 |
11 | function AccountAccessTokenFixture(){
12 | }
13 |
14 | AccountAccessTokenFixture.prototype.before = function before(done) {
15 | var self = this;
16 | helpers.getClient(function(_client){
17 |
18 | self.client = _client;
19 | helpers.createApplication(function(err,app){
20 | if (err) {
21 | return done(err);
22 | }
23 |
24 | self.application = app;
25 | helpers.getDefaultAccountStore(app,function(err,dir){
26 | if (err) {
27 | return done(err);
28 | }
29 |
30 | self.directory = dir;
31 | self.newAccount = helpers.fakeAccount();
32 | dir.createAccount(self.newAccount, function(err,_account) {
33 | self.account = _account;
34 | self.creationResult = [err, _account];
35 |
36 | /*
37 | We need to do a password grant request, so that we create
38 | an access token and refresh token for this user
39 | */
40 |
41 | var authenticator = new OAuthPasswordGrantRequestAuthenticator(app);
42 | authenticator.authenticate({
43 | username: _account.username,
44 | password: self.newAccount.password
45 | },function(err,passwordGrantResult){
46 | if(err){
47 | done(err);
48 | }else{
49 | self.passwordGrantResult = passwordGrantResult;
50 | done();
51 | }
52 | });
53 | });
54 |
55 | });
56 |
57 |
58 | });
59 | });
60 | };
61 | AccountAccessTokenFixture.prototype.after = function after(done) {
62 | helpers.cleanupApplicationAndStores(this.application, done);
63 | };
64 |
65 | module.exports = AccountAccessTokenFixture;
66 |
--------------------------------------------------------------------------------
/test/fixtures/apiKey.properties:
--------------------------------------------------------------------------------
1 | apiKey.id = api_key_id
2 | apiKey.secret = api_key_secret
3 |
--------------------------------------------------------------------------------
/test/it/assertion_authentication_result_it.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var common = require('../common');
4 | var DataStore = require('../../lib/ds/DataStore');
5 |
6 | var assert = common.assert;
7 | var sinon = common.sinon;
8 | var stormpath = common.Stormpath;
9 |
10 | var AssertionAuthenticationResult = stormpath.AssertionAuthenticationResult;
11 |
12 | describe('AssertionAuthenticationResult', function () {
13 |
14 | var authenticationResult;
15 | var sandbox;
16 | var dataStore;
17 |
18 | var mockAccount = {
19 | href: 'http://stormpath.mock/api/v1/account/123',
20 | name: 'foo'
21 | };
22 |
23 | before(function () {
24 |
25 | dataStore = new DataStore({
26 | client: {
27 | apiKey: {
28 | id: 'abc',
29 | secret: '123'
30 | }
31 | }
32 | });
33 |
34 | sandbox = sinon.sandbox.create();
35 |
36 | var data = {
37 | account: {
38 | href: mockAccount.href
39 | },
40 | dataStore: {
41 | foo: 'this dataStore propety should be ignored, as it will already be defined by the first dataStore parmater'
42 | }
43 | };
44 |
45 | authenticationResult = new AssertionAuthenticationResult(dataStore, data);
46 |
47 | sandbox.stub(dataStore, 'getResource', function (href, data, callback) {
48 | callback(null, mockAccount);
49 | });
50 | });
51 |
52 | after(function () {
53 | sandbox.restore();
54 | });
55 |
56 | describe('when constructed', function () {
57 |
58 | it('should apply the data store parmater to the object', function(){
59 | assert.equal(authenticationResult.dataStore, dataStore);
60 | });
61 |
62 | it('should apply the data parmater properties to the object', function(){
63 | assert.ok(authenticationResult.account);
64 | assert.equal(authenticationResult.account.href, mockAccount.href);
65 | });
66 | });
67 |
68 | describe('.getAccount()', function () {
69 |
70 | it('should error if no account is defined', function(done) {
71 | new AssertionAuthenticationResult({},{}).getAccount(function(err){
72 | assert.isOk(err);
73 | assert.equal(err.message, 'Unable to get account. Account HREF not specified.');
74 | done();
75 | });
76 | });
77 |
78 | it('should call the callback with the account result', function (done) {
79 | authenticationResult.getAccount(function (err, result) {
80 | assert.notOk(err);
81 | assert.deepEqual(result, mockAccount);
82 | done();
83 | });
84 | });
85 | });
86 | });
--------------------------------------------------------------------------------
/test/it/datastore_it.js:
--------------------------------------------------------------------------------
1 |
2 | var common = require('../common');
3 | var helpers = require('./helpers');
4 | var assert = common.assert;
5 |
6 | describe('DataStore', function() {
7 | describe('when asked for a resource', function() {
8 | var cacheResult, resource;
9 |
10 | before(function(done) {
11 | helpers.getClient(function(client) {
12 | client.getCurrentTenant(function(err, tenant) {
13 | assert.ifError(err);
14 | resource = tenant;
15 |
16 | client._dataStore.cacheHandler.get(tenant.href, function(err, value) {
17 | assert.ifError(err);
18 | cacheResult = value;
19 | done();
20 | });
21 | });
22 | });
23 | });
24 |
25 | it('should cache the resource', function() {
26 | assert.equal(cacheResult.href, resource.href);
27 | });
28 | });
29 |
30 | describe('when asked for a collection',function(){
31 | var cacheResult;
32 |
33 | before(function(done){
34 | helpers.getClient(function(client){
35 | client.getCurrentTenant(function(err,tenant){
36 | if(err){throw err;}
37 | tenant.getApplications(function(err,collection){
38 | if(err){throw err;}
39 | client._dataStore.cacheHandler.get(collection.href,function(err,value){
40 | if(err){throw err;}
41 | cacheResult = value;
42 | done();
43 | });
44 | });
45 | });
46 | });
47 | });
48 |
49 | it('should not cache the collection',function(){
50 | assert.equal(cacheResult,null);
51 | });
52 | });
53 |
54 | describe('when asked for a previously created resource w/ expansions,',function(){
55 | var directory, expandedDirectory;
56 | before(function(done){
57 | helpers.getClient(function(client){
58 |
59 | client.createDirectory(helpers.fakeDirectory(),function(err,_directory){
60 | if(err){throw err;}
61 | directory = _directory;
62 | client.getDirectory(directory.href,{expand:'customData'},function(err,_directory){
63 | if(err){throw err;}
64 | expandedDirectory = _directory;
65 | done();
66 | });
67 | });
68 | });
69 | });
70 | after(function(done){
71 | directory.delete(done);
72 | });
73 | it('should return the resource w/ expansions',function(){
74 | assert.equal(typeof expandedDirectory.customData.createdAt,'string');
75 | });
76 |
77 | });
78 |
79 | });
80 |
--------------------------------------------------------------------------------
/test/it/oauth_id_site_token_grant_it.js:
--------------------------------------------------------------------------------
1 | var common = require('../common');
2 | var helpers = require('./helpers');
3 | var assert = common.assert;
4 |
5 | var stormpath = require('../../');
6 |
7 | describe('OAuthIdSiteTokenGrantAuthenticator',function(){
8 | var application;
9 | var newAccount;
10 |
11 | before(function(done){
12 | newAccount = helpers.fakeAccount();
13 |
14 | helpers.createApplication(function(err,app){
15 | application = app;
16 | application.createAccount(newAccount,done);
17 | });
18 | });
19 |
20 | after(function(done){
21 | helpers.cleanupApplicationAndStores(application, done);
22 | });
23 |
24 | it('should be constructable with new operator',function(){
25 | var authenticator = new stormpath.OAuthIdSiteTokenGrantAuthenticator(application);
26 | assert.instanceOf(authenticator, stormpath.OAuthIdSiteTokenGrantAuthenticator);
27 | });
28 |
29 | it('should be constructable without new operator',function(){
30 | var authenticator = stormpath.OAuthIdSiteTokenGrantAuthenticator(application);
31 | assert.instanceOf(authenticator, stormpath.OAuthIdSiteTokenGrantAuthenticator);
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/test/it/oauth_refresh_grant_it.js:
--------------------------------------------------------------------------------
1 |
2 | var common = require('../common');
3 | var helpers = require('./helpers');
4 | var assert = common.assert;
5 |
6 | var stormpath = require('../../');
7 |
8 | describe('OAuthRefreshTokenGrantRequestAuthenticator',function(){
9 |
10 | var application, refreshToken;
11 |
12 | var newAccount;
13 |
14 | before(function(done){
15 | newAccount = helpers.fakeAccount();
16 |
17 | helpers.createApplication(function(err,app){
18 | if(err){
19 | done(err);
20 | }else{
21 | application = app;
22 | application.createAccount(newAccount,function(err){
23 | if(err){
24 | done(err);
25 | }else{
26 | var authenticator = new stormpath.OAuthPasswordGrantRequestAuthenticator(application);
27 | authenticator.authenticate({
28 | username: newAccount.username,
29 | password: newAccount.password
30 | },function(err,passwordGrantResult){
31 | if(err){
32 | done(err);
33 | }else{
34 | refreshToken = passwordGrantResult.refreshToken;
35 | done();
36 | }
37 | });
38 | }
39 | });
40 | }
41 |
42 | });
43 | });
44 |
45 | after(function(done){
46 | helpers.cleanupApplicationAndStores(application, done);
47 | });
48 |
49 | it('should be constructable with new operator',function(){
50 | var authenticator = new stormpath.OAuthRefreshTokenGrantRequestAuthenticator(application);
51 | assert.instanceOf(authenticator,stormpath.OAuthRefreshTokenGrantRequestAuthenticator);
52 | });
53 |
54 | it('should be constructable without new operator',function(){
55 | var authenticator = stormpath.OAuthRefreshTokenGrantRequestAuthenticator(application);
56 | assert.instanceOf(authenticator,stormpath.OAuthRefreshTokenGrantRequestAuthenticator);
57 | });
58 |
59 | it('should refresh access tokens',function(done){
60 | var authenticator = new stormpath.OAuthRefreshTokenGrantRequestAuthenticator(application);
61 | authenticator.authenticate({
62 | refresh_token: refreshToken.toString()
63 | },function(err,response){
64 | common.assertAccessTokenResponse(response);
65 | done();
66 | });
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/test/it/organization_it.js:
--------------------------------------------------------------------------------
1 |
2 | var common = require('../common');
3 | var helpers = require('./helpers');
4 | var assert = common.assert;
5 | var async = require('async');
6 |
7 | var Organization = require('../../lib/resource/Organization');
8 | var OrganizationAccountStoreMapping = require('../../lib/resource/OrganizationAccountStoreMapping');
9 |
10 | describe('Organization',function(){
11 |
12 | var client, organization, directory, mapping;
13 |
14 | before(function(done) {
15 | helpers.getClient(function(_client) {
16 | client = _client;
17 | var org = {
18 | name: helpers.uniqId(),
19 | nameKey: helpers.uniqId()
20 | };
21 | var dir = {
22 | name: helpers.uniqId()
23 | };
24 | client.createOrganization(org, function(err, _organization) {
25 | if(err){ throw err; }
26 | organization = _organization;
27 |
28 | client.createDirectory(dir,function(err,_directory){
29 | if(err){ throw err; }
30 | directory = _directory;
31 | done();
32 | });
33 |
34 |
35 | });
36 | });
37 | });
38 |
39 | after(function(done) {
40 | async.eachSeries([mapping,directory, organization ], function(resource, next) {
41 | resource.delete(next);
42 | }, done);
43 | });
44 |
45 | describe('createAccountStoreMapping',function(){
46 | after(function(done){
47 | mapping.delete(done);
48 | });
49 | it('should create an OrganizationAccountStoreMapping',function(done){
50 | organization.createAccountStoreMapping({accountStore:directory},function(err,_mapping){
51 | mapping = _mapping;
52 | assert(_mapping instanceof OrganizationAccountStoreMapping);
53 | done();
54 | });
55 | });
56 | it('should handle errors',function(done){
57 | organization.createAccountStoreMapping({accountStore:{href:'not found'}},function(err){
58 | assert(err.status === 400);
59 | assert(err.code === 2002);
60 | done();
61 | });
62 | });
63 | });
64 |
65 | describe('getOrganization',function(){
66 | after(function(done){
67 | mapping.delete(done);
68 | });
69 | it('should return the organization',function(done){
70 | mapping.getOrganization(function(err,organization){
71 | assert(organization instanceof Organization);
72 | done();
73 | });
74 | });
75 | });
76 |
77 | describe('createAccountStoreMappings',function(){
78 | it('should create an OrganizationAccountStoreMapping',function(done){
79 | organization.createAccountStoreMappings([{accountStore:directory}],function(err,results){
80 | if(err){
81 | done(err);
82 | }else{
83 | assert(results[0] instanceof OrganizationAccountStoreMapping);
84 | mapping = results[0];
85 | done();
86 | }
87 | });
88 | });
89 | });
90 |
91 | describe('getAccountStoreMappings',function(){
92 | it('should get an OrganizationAccountStoreMapping',function(done){
93 | organization.getAccountStoreMappings(function(err,collection){
94 | assert(collection.items[0] instanceof OrganizationAccountStoreMapping);
95 | done();
96 | });
97 | });
98 | });
99 |
100 | });
101 |
--------------------------------------------------------------------------------
/test/it/password_policy_it.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var assert = require('assert');
4 | var uuid = require('uuid');
5 | var Client = require('../../lib/Client');
6 |
7 | describe('PasswordPolicy', function() {
8 | describe('getStrength', function() {
9 | var client, directory;
10 |
11 | before(function (done) {
12 | client = new Client();
13 |
14 | client.on('error', function (err) {
15 | done(err);
16 | });
17 |
18 | client.on('ready', function () {
19 | done();
20 | });
21 | });
22 |
23 | after(function (done) {
24 | directory.delete(function(err) {
25 | done(err);
26 | });
27 | });
28 |
29 | it('should return the strength object', function (done) {
30 | client.createDirectory({ name: uuid.v4() }, function (err, dir) {
31 | if (err) {
32 | return done(err);
33 | }
34 |
35 | directory = dir;
36 |
37 | directory.getPasswordPolicy(function (err, policy) {
38 | if (err) {
39 | return done(err);
40 | }
41 |
42 | policy.getStrength(function (err, strength) {
43 | if (err) {
44 | return done(err);
45 | }
46 |
47 | assert(strength.href);
48 | done();
49 | });
50 | });
51 | });
52 | });
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/test/it/saml_idp_url_builder_it.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var nJwt = require('njwt');
4 | var url = require('url');
5 | var helpers = require('./helpers');
6 | var common = require('../common');
7 |
8 | var assert = common.assert;
9 | var stormpath = common.Stormpath;
10 |
11 | var SamlIdpUrlBuilder = stormpath.SamlIdpUrlBuilder;
12 |
13 | describe('SamlIdpUrlBuilder', function () {
14 | var builder, application;
15 |
16 | before(function (done) {
17 | application = helpers.createApplication(function (err, app) {
18 | if (err) {
19 | return done(err);
20 | }
21 |
22 | application = app;
23 | builder = new SamlIdpUrlBuilder(app);
24 |
25 | done();
26 | });
27 | });
28 |
29 | after(function(done){
30 | helpers.cleanupApplicationAndStores(application, done);
31 | });
32 |
33 | describe('.build()', function () {
34 | describe('without options', function () {
35 | it('should return a valid url', function (done) {
36 | builder.build(function (err, resultUrl) {
37 | assert.isNotOk(err);
38 | assert.isOk(resultUrl);
39 |
40 | var parsedUrl = url.parse(resultUrl, true);
41 |
42 | assert.ok(parsedUrl);
43 | assert.equal(parsedUrl.pathname, url.parse(application.href).pathname + '/saml/sso/idpRedirect');
44 | assert.isDefined(parsedUrl.query.accessToken);
45 |
46 | done();
47 | });
48 | });
49 | });
50 | describe('with options', function () {
51 | it('should encode those options in the accessToken', function (done) {
52 | var options = {
53 | cb_uri: 'http://mysite.com/samlCallback',
54 | onk: 'my-org',
55 | ash: 'https://api.stormpath.com/v1/directories/:dirId',
56 | state: 'hello'
57 | };
58 | builder.build(options, function (err, resultUrl) {
59 | assert.isNull(err);
60 | assert.isOk(resultUrl);
61 |
62 | var parsedUrl = url.parse(resultUrl, true);
63 |
64 | var secret = application.dataStore.requestExecutor.options.client.apiKey.secret;
65 |
66 | assert.isDefined(parsedUrl.query.accessToken);
67 |
68 | var jwt = nJwt.verify(parsedUrl.query.accessToken, secret);
69 |
70 | assert.equal(jwt.body.cb_uri, options.cb_uri);
71 | assert.equal(jwt.body.onsk, options.onsk);
72 | assert.equal(jwt.body.ash, options.ash);
73 | assert.equal(jwt.body.state, options.state);
74 |
75 | done();
76 | });
77 | });
78 | });
79 | });
80 | });
81 |
--------------------------------------------------------------------------------
/test/sp.authc.apiKeyLoader_test.js:
--------------------------------------------------------------------------------
1 | /* jshint -W030 */
2 | 'use strict';
3 |
4 | var common = require('./common');
5 | var expect = common.expect;
6 |
7 | var ApiKey = require('../lib/authc/ApiKey');
8 | var loadApiKey = require('../lib/authc/ApiKeyLoader');
9 |
10 | var path = './test/fixtures/apiKey.properties';
11 |
12 | describe('authc', function () {
13 | describe('ApiKey loader', function(){
14 | it('should load prefixed file path with file://', function(done){
15 | loadApiKey('file://' + path, function(err, apiKey){
16 | expect(err).to.be.null;
17 | apiKey.should.be.ok;
18 | done();
19 | });
20 | });
21 | it('should load preferences with relative file path', function(done){
22 | loadApiKey(path, function(err, apiKey){
23 | expect(err).to.be.null;
24 | apiKey.should.be.ok;
25 | done();
26 | });
27 | });
28 | it('should return error in callback if path is wrong', function(done){
29 | loadApiKey('boom' + path, function(err, apiKey){
30 | err.should.be.an.instanceof(Error);
31 | err.message.should.match(/unable to read/i);
32 | expect(apiKey).to.be.null;
33 | done();
34 | });
35 | });
36 | it('should return instance of ApiKey with loaded params', function(done){
37 | loadApiKey(path, function(err, apiKey){
38 | apiKey.should.be.an.instanceof(ApiKey);
39 | apiKey.id.should.be.equal('api_key_id');
40 | apiKey.secret.should.be.equal('api_key_secret');
41 | done();
42 | });
43 | });
44 | });
45 | });
--------------------------------------------------------------------------------
/test/sp.authc.apiKey_test.js:
--------------------------------------------------------------------------------
1 | /* jshint -W030 */
2 | 'use strict';
3 |
4 | var ApiKey = require('../lib/authc/ApiKey');
5 |
6 | describe('authc', function () {
7 | describe('ApiKey class', function(){
8 | var id;
9 | var secret;
10 | var apiKey;
11 |
12 | before(function () {
13 | id = 'id';
14 | secret = 'boom!';
15 | apiKey = new ApiKey(id, secret);
16 | });
17 |
18 | it('should expose id and secret as fields', function(){
19 | apiKey.id.should.be.equal(id);
20 | apiKey.secret.should.be.equal(secret);
21 | });
22 | it('should hide secret', function(){
23 | apiKey.toString().should.contain(id);
24 | apiKey.toString().should.not.contain(secret);
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/test/sp.authc.authRequestParser_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var assert = require('assert');
4 |
5 | var AuthRequestParser = require('../lib/authc/AuthRequestParser');
6 |
7 | describe('AuthRequestParser', function() {
8 | it('should throw an error if request is not an object', function() {
9 | assert.throws(function() {
10 | new AuthRequestParser('test', 'woo');
11 | }, Error);
12 | });
13 |
14 | it('should throw an error if request.url is not a string', function() {
15 | assert.throws(function() {
16 | new AuthRequestParser({
17 | body: null,
18 | headers: {},
19 | method: 'get',
20 | url: 1,
21 | }, ['body']);
22 | }, Error);
23 | });
24 |
25 | it('should throw an error if locationsToSearch is not an array', function() {
26 | assert.throws(function() {
27 | new AuthRequestParser({
28 | body: null,
29 | headers: {},
30 | method: 'get',
31 | url: 'test'
32 | }, 'woo');
33 | }, Error);
34 | });
35 |
36 | it('should throw an error if request.method is not a string', function() {
37 | assert.throws(function() {
38 | new AuthRequestParser({ method: 1 }, {});
39 | }, Error);
40 | });
41 |
42 | it('should throw an error if request.headers is not an object', function() {
43 | assert.throws(function() {
44 | new AuthRequestParser({ headers: 'test', method: 'get' }, {});
45 | }, Error);
46 | });
47 |
48 | it('should allow the request.body to be null', function() {
49 | var parser = new AuthRequestParser({
50 | body: null,
51 | headers: {},
52 | method: 'get',
53 | url: 'test'
54 | }, ['body']);
55 |
56 | assert.equal(Object.keys(parser.body).length, 0);
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/test/sp.authc.requestAuthenticator_test.js:
--------------------------------------------------------------------------------
1 | /* jshint -W030 */
2 | 'use strict';
3 |
4 | var RequestAuthenticator = require('../lib/authc/RequestAuthenticator');
5 |
6 | describe('authc', function () {
7 | describe('RequestAuthenticator class', function () {
8 | function createAuth(apiKey){
9 | return function(){
10 | return new RequestAuthenticator(apiKey);
11 | };
12 | }
13 | describe('if apiKey not provided', function () {
14 | it('should throw api key is required exception', function () {
15 | createAuth(null).should.throw(/apiKey is required/i);
16 | });
17 | });
18 |
19 | describe('if apiKey.id not provided', function () {
20 | it('should throw apiKey.id is required', function () {
21 | createAuth({}).should.throw(/apiKey.id is required/);
22 | });
23 | });
24 | describe('if apiKey.secret not provided', function () {
25 | it('should throw apiKey.secret is required', function () {
26 | createAuth({id: 1}).should.throw(/apiKey.secret is required/);
27 | });
28 | });
29 | });
30 | });
--------------------------------------------------------------------------------
/test/sp.cache.disabledCache_test.js:
--------------------------------------------------------------------------------
1 | var common = require('./common');
2 | var _ = common._;
3 | var should = common.should;
4 |
5 | describe('Cache module',function(){
6 |
7 | describe('DisabledCache cache stub', function(){
8 | var DisabledCache = require('../lib/cache/DisabledCache');
9 | var disabledCache = new DisabledCache();
10 | function callToMethod(cache, methodName){
11 | describe('call to',function(){
12 | it(methodName+ ' method should return null, null', function(done){
13 | cache[methodName](function(err, res){
14 | should.not.exist(err);
15 | should.not.exist(res);
16 | done();
17 | });
18 | });
19 | });
20 | }
21 | _.each(disabledCache.prototype, function(method, methodName){
22 | callToMethod(disabledCache,methodName);
23 | });
24 | });
25 | });
--------------------------------------------------------------------------------
/test/sp.cache.manager_test.js:
--------------------------------------------------------------------------------
1 | var common = require('./common');
2 | var should = common.should;
3 | var expect = common.expect;
4 |
5 | var CacheManager = require('../lib/cache/CacheManager');
6 |
7 | describe('Cache module',function(){
8 |
9 | describe('Cache Manager class', function(){
10 | describe('By default', function(){
11 | var manager;
12 |
13 | before(function () {
14 | manager = new CacheManager();
15 | });
16 |
17 | it('cache should be empty', function(){
18 | /* jshint -W030 */
19 | manager.caches.should.deep.equal({});
20 | });
21 | it('stats should be empty', function(){
22 | /* jshint -W030 */
23 | expect(manager.stats).deep.equal({});
24 | });
25 | });
26 |
27 | describe('create cache',function(){
28 | var manager;
29 | var region;
30 |
31 | before(function(){
32 | manager = new CacheManager();
33 | region = common.uuid();
34 |
35 | manager.createCache(region);
36 | });
37 | it('should create cache instance', function(){
38 | should.exist(manager.getCache(region));
39 | });
40 | it('should add stats', function (){
41 | should.exist(manager.stats);
42 | });
43 | });
44 |
45 | describe('get cache',function(){
46 | var manager;
47 | var region;
48 |
49 | before(function(){
50 | manager = new CacheManager();
51 | region = common.uuid();
52 |
53 | manager.createCache(region);
54 | });
55 | it('should return cache instance', function(){
56 | should.exist(manager.getCache(region));
57 | });
58 | });
59 | });
60 | });
61 |
--------------------------------------------------------------------------------
/test/sp.cache.memoryStore_test.js:
--------------------------------------------------------------------------------
1 | var common = require('./common');
2 | var should = common.should;
3 |
4 | var MemoryStore = require('../lib/cache/MemoryStore');
5 |
6 | describe('Cache module', function () {
7 |
8 | describe('In memory cache store', function () {
9 | var memoryStore;
10 |
11 | before(function () {
12 | memoryStore = new MemoryStore();
13 | });
14 |
15 | describe('set entry', function () {
16 | var key;
17 | var val;
18 | var entry;
19 |
20 | before(function (done) {
21 | key = 'key' + Date.now();
22 | val = 'val' + Date.now();
23 |
24 | memoryStore.set(key, val, function () {
25 | memoryStore.get(key, function (err, ent) {
26 | entry = ent;
27 | done();
28 | });
29 | });
30 | });
31 | after(function (done) {
32 | memoryStore.delete(key, done);
33 | });
34 | it('should store value', function () {
35 | should.exist(entry);
36 | });
37 | it('stored value should be accessible', function () {
38 | entry.should.be.equal(val);
39 | });
40 | });
41 |
42 | describe('get entry', function () {
43 | var key;
44 | var val;
45 |
46 | before(function (done) {
47 | key = 'key' + Date.now();
48 | val = 'val' + Date.now();
49 |
50 | memoryStore.set(key, val, done);
51 | });
52 | after(function (done) {
53 | memoryStore.delete(key, done);
54 | });
55 |
56 | it('should return entry if found', function (done) {
57 | memoryStore.get(key, function (err, entry) {
58 | should.not.exist(err);
59 | should.exist(entry);
60 | entry.should.be.equal(val);
61 | done();
62 | });
63 | });
64 | it('should return null if not found', function (done) {
65 | memoryStore.get(Date.now(), function (err, entry) {
66 | should.not.exist(err);
67 | should.not.exist(entry);
68 | done();
69 | });
70 | });
71 | });
72 |
73 | describe('delete entry', function () {
74 | var key;
75 | var val;
76 |
77 | before(function (done) {
78 | key = 'key' + Date.now();
79 | val = 'val' + Date.now();
80 |
81 | memoryStore.set(key, val, done);
82 | });
83 | it('should remove entry from store', function (done) {
84 | memoryStore.delete(key, function () {
85 | memoryStore.get(key, function (err, entry) {
86 | should.not.exist(entry);
87 | done();
88 | });
89 | });
90 | });
91 | });
92 |
93 | describe('clear cache', function () {
94 | var key;
95 | var val;
96 |
97 | before(function (done) {
98 | key = 'key' + Date.now();
99 | val = 'val' + Date.now();
100 |
101 | memoryStore.set(key, val, done);
102 | });
103 | it('should remove all entries from store', function (done) {
104 | memoryStore.clear(function () {
105 | memoryStore.get(key, function (err, entry) {
106 | should.not.exist(entry);
107 | done();
108 | });
109 | });
110 | });
111 | });
112 |
113 | describe('cache size', function () {
114 | var key;
115 | var val;
116 |
117 | before(function (done) {
118 | key = 'key' + Date.now();
119 | val = 'val' + Date.now();
120 |
121 | memoryStore.clear(function(){
122 | memoryStore.set(key, val, done);
123 | });
124 | });
125 | it('should return store size', function (done) {
126 | memoryStore.size(function (err, size) {
127 | size.should.be.equal(1);
128 | done();
129 | });
130 | });
131 | });
132 | });
133 | });
134 |
--------------------------------------------------------------------------------
/test/sp.cache.stats_test.js:
--------------------------------------------------------------------------------
1 | var CacheStats = require('../lib/cache/CacheStats');
2 |
3 | describe('Cache module',function(){
4 |
5 | // make sens only for single instance!!!
6 | describe('Cache Stats class', function(){
7 | var stats;
8 |
9 | before(function () {
10 | stats = new CacheStats();
11 | });
12 |
13 | describe('if we put a new entry', function(){
14 | var putsCounter, sizeCounter;
15 | before(function(){
16 | putsCounter = stats.puts;
17 | sizeCounter = stats.size;
18 | stats.put(true);
19 | });
20 | it('should increase puts counter', function(){
21 | stats.puts.should.be.equal(putsCounter + 1);
22 | });
23 | it('should increase size counter', function(){
24 | stats.size.should.be.equal(sizeCounter + 1);
25 | });
26 | });
27 |
28 | describe('if we put an old entry', function(){
29 | var putsCounter, sizeCounter;
30 | before(function(){
31 | putsCounter = stats.puts;
32 | sizeCounter = stats.size;
33 |
34 | stats.put(false);
35 | });
36 | it('should increase puts counter', function(){
37 | stats.puts.should.be.equal(putsCounter + 1);
38 | });
39 | it('should not increase size counter', function(){
40 | stats.size.should.be.equal(sizeCounter);
41 | });
42 | });
43 |
44 | describe('if we hit an entry', function(){
45 | var hitsCounter;
46 | before(function(){
47 | hitsCounter = stats.hits;
48 |
49 | stats.hit();
50 | });
51 | it('should increase hits counter', function(){
52 | stats.hits.should.be.equal(hitsCounter + 1);
53 | });
54 | });
55 |
56 | describe('if we miss a new entry', function(){
57 | var missesCounter,expirationsCounter;
58 | before(function(){
59 | missesCounter = stats.misses;
60 | expirationsCounter = stats.expirations;
61 |
62 | stats.miss(true);
63 | });
64 |
65 | it('should increase misses counter',function(){
66 | stats.misses.should.be.equal(missesCounter + 1);
67 | });
68 | it('should increase expirations counter', function(){
69 | stats.expirations.should.be.equal(expirationsCounter + 1);
70 | });
71 | });
72 |
73 | describe('if we miss an expired entry', function(){
74 | var missesCounter,expirationsCounter;
75 | before(function(){
76 | missesCounter = stats.misses;
77 | expirationsCounter = stats.expirations;
78 |
79 | stats.miss(false);
80 | });
81 | it('should increase misses counter', function(){
82 | stats.misses.should.be.equal(missesCounter + 1);
83 | });
84 | it('should not increase expirations counter', function(){
85 | stats.expirations.should.be.equal(expirationsCounter);
86 | });
87 | });
88 |
89 | describe('if we delete an entry from cache', function(){
90 | var sizeCounter;
91 | before(function(){
92 | sizeCounter = stats.size;
93 |
94 | stats.delete();
95 | });
96 | it('should decrease size counter', function(){
97 | stats.size.should.be.equal(sizeCounter - 1);
98 | });
99 | });
100 |
101 | describe('if we delete an entry from empty cache', function(){
102 | before(function(){
103 | stats.clear();
104 | stats.delete();
105 | });
106 | it('should not decrease size counter', function(){
107 | stats.size.should.be.equal(0);
108 | });
109 | });
110 |
111 | describe('if we clear cache', function(){
112 | before(function(){
113 | stats.clear();
114 | });
115 | it('should reset size counter', function(){
116 | stats.size.should.be.equal(0);
117 | });
118 | });
119 | });
120 | });
121 |
--------------------------------------------------------------------------------
/test/sp.error.resourceError_test.js:
--------------------------------------------------------------------------------
1 | var ResourceError = require('../lib/error/ResourceError');
2 |
3 | describe('Error:', function () {
4 | describe('Resource Error', function () {
5 | var response;
6 | var re;
7 |
8 | before(function () {
9 | response = {
10 | status: 400,
11 | code: 100500,
12 | message: 'hi user',
13 | developerMessage: 'hi dev',
14 | moreInfo: 'boom!'
15 | };
16 |
17 | re = new ResourceError(response);
18 | });
19 |
20 | it('should inherit from error', function () {
21 | re.should.be.an.instanceof(Error);
22 | });
23 |
24 | it('should dispose response fields', function () {
25 | re.name.should.match(/ResourceError/i);
26 | re.status.should.be.equal(response.status);
27 | re.code.should.be.equal(response.code);
28 | re.userMessage.should.be.equal(response.message);
29 | re.developerMessage.should.be.equal(response.developerMessage);
30 | re.moreInfo.should.be.equal(response.moreInfo);
31 | });
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/test/sp.resource.accountLink_test.js:
--------------------------------------------------------------------------------
1 | var common = require('./common');
2 | var assert = common.assert;
3 | var sinon = common.sinon;
4 |
5 | var Account = require('../lib/resource/Account');
6 | var AccountLink = require('../lib/resource/AccountLink');
7 | var DataStore = require('../lib/ds/DataStore');
8 |
9 | describe('Resources: ', function() {
10 | describe('AccountLink resource class', function() {
11 | var dataStore;
12 |
13 | before(function () {
14 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
15 | });
16 |
17 | describe('Constructor', function() {
18 | it('should inherit from InstanceResource', function() {
19 | AccountLink.super_.name.should.equal('InstanceResource');
20 | });
21 | });
22 |
23 | describe('methods', function() {
24 | var sandbox;
25 | var opts;
26 | var accountLinkData;
27 | var accountLink;
28 | var getResourceStub;
29 | var cbSpy;
30 |
31 | before(function() {
32 | sandbox = sinon.sandbox.create();
33 |
34 | opts = {
35 | boom: 'of course'
36 | };
37 |
38 | accountLinkData = {
39 | href: 'boom!',
40 | createdAt: '',
41 | modifiedAt: '',
42 | leftAccount: {
43 | href: 'leftBoom!'
44 | },
45 | rightAccount: {
46 | href: 'rightBoom!'
47 | }
48 | };
49 |
50 | accountLink = new AccountLink(accountLinkData, dataStore);
51 |
52 | getResourceStub = sandbox.stub(dataStore, 'getResource', function(href, options, ctor, cb) {
53 | cb();
54 | });
55 |
56 | cbSpy = sandbox.spy();
57 | });
58 |
59 | after(function() {
60 | sandbox.restore();
61 | });
62 |
63 | describe('#getLeftAccount()', function() {
64 | before(function() {
65 | accountLink.getLeftAccount(cbSpy);
66 | accountLink.getLeftAccount(opts, cbSpy);
67 | });
68 |
69 | it('should get the leftAccount resource', function() {
70 | /* jshint -W030 */
71 | getResourceStub.should.have.been.calledTwice;
72 | cbSpy.should.have.been.calledTwice;
73 | /* jshint +W030 */
74 |
75 | getResourceStub.should.have.been.calledWith(
76 | 'leftBoom!',
77 | null,
78 | Account,
79 | cbSpy
80 | );
81 |
82 | getResourceStub.should.have.been.calledWith(
83 | 'leftBoom!',
84 | opts,
85 | Account,
86 | cbSpy
87 | );
88 | });
89 | });
90 |
91 | describe('#getRightAccount()', function() {
92 | before(function() {
93 | accountLink.getRightAccount(cbSpy);
94 | accountLink.getRightAccount(opts, cbSpy);
95 | });
96 |
97 | it('should get the rightAccount resource', function() {
98 | assert.equal(getResourceStub.callCount, 4);
99 | assert.equal(cbSpy.callCount, 4);
100 |
101 | getResourceStub.should.have.been.calledWith(
102 | 'rightBoom!',
103 | null,
104 | Account,
105 | cbSpy
106 | );
107 |
108 | getResourceStub.should.have.been.calledWith(
109 | 'rightBoom!',
110 | opts,
111 | Account,
112 | cbSpy
113 | );
114 | });
115 | });
116 | });
117 | });
118 | });
119 |
--------------------------------------------------------------------------------
/test/sp.resource.accountLinkingPolicy_test.js:
--------------------------------------------------------------------------------
1 | var common = require('./common');
2 | var assert = common.assert;
3 | var sinon = common.sinon;
4 |
5 | var AccountLinkingPolicy = require('../lib/resource/AccountLinkingPolicy');
6 | var Tenant = require('../lib/resource/Tenant');
7 | var DataStore = require('../lib/ds/DataStore');
8 |
9 | describe('Resources: ', function() {
10 | describe('AccountLinkingPolicy resource class', function() {
11 | var dataStore;
12 |
13 | before(function() {
14 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
15 | });
16 |
17 | describe('Constructor', function() {
18 | it('should inherit from InstanceResource', function() {
19 | AccountLinkingPolicy.super_.name.should.equal('InstanceResource');
20 | });
21 |
22 | it('should *not* inherit the delete method', function() {
23 | var alp = new AccountLinkingPolicy({href: 'boom!'}, dataStore);
24 | assert.isUndefined(alp.delete);
25 | });
26 | });
27 |
28 | describe('methods', function() {
29 | var sandbox;
30 | var opts;
31 | var alpData;
32 | var alp;
33 | var getResourceStub;
34 | var cbSpy;
35 |
36 | before(function() {
37 | sandbox = sinon.sandbox.create();
38 |
39 | opts = {
40 | boom: 'of course'
41 | };
42 |
43 | alpData = {
44 | href: 'boom!',
45 | createdAt: '',
46 | modifiedAt: '',
47 | status: 'ENABLED',
48 | automaticProvisioning: 'ENABLED',
49 | matchingProperty: 'email',
50 | tenant: {
51 | href: 'boom!'
52 | }
53 | };
54 |
55 | alp = new AccountLinkingPolicy(alpData, dataStore);
56 |
57 | getResourceStub = sandbox.stub(dataStore, 'getResource', function(href, options, ctor, cb) {
58 | cb();
59 | });
60 |
61 | cbSpy = sandbox.spy();
62 | });
63 |
64 | after(function() {
65 | sandbox.restore();
66 | });
67 |
68 | describe('#getTenant()', function() {
69 | before(function() {
70 | alp.getTenant(cbSpy);
71 | alp.getTenant(opts, cbSpy);
72 | });
73 |
74 | it('should get the leftAccount resource', function() {
75 | /* jshint -W030 */
76 | getResourceStub.should.have.been.calledTwice;
77 | cbSpy.should.have.been.calledTwice;
78 | /* jshint +W030 */
79 |
80 | getResourceStub.should.have.been.calledWith(
81 | 'boom!',
82 | null,
83 | Tenant,
84 | cbSpy
85 | );
86 |
87 | getResourceStub.should.have.been.calledWith(
88 | 'boom!',
89 | opts,
90 | Tenant,
91 | cbSpy
92 | );
93 | });
94 | });
95 | });
96 | });
97 | });
98 |
--------------------------------------------------------------------------------
/test/sp.resource.apikey_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var assert = require('assert');
4 | var sinon = require('sinon');
5 | var uuid = require('uuid');
6 |
7 | var ApiKey = require('../lib/resource/ApiKey');
8 | var DataStore = require('../lib/ds/DataStore');
9 |
10 | describe('resource', function() {
11 | describe('ApiKey', function() {
12 | var clientApiKeySecret, sandbox, cbSpy, apiKey, getResourceStub;
13 |
14 | before(function(done) {
15 | clientApiKeySecret = uuid();
16 | sandbox = sinon.sandbox.create();
17 | cbSpy = sandbox.spy();
18 |
19 | apiKey = new ApiKey({
20 | id: 'id',
21 | secret: 'secret',
22 | account: {
23 | href: '/boom'
24 | }
25 | });
26 |
27 | apiKey.dataStore = new DataStore({
28 | client: {
29 | apiKey: {
30 | id: '1',
31 | secret: clientApiKeySecret
32 | }
33 | }
34 | });
35 |
36 | getResourceStub = sinon.stub(apiKey.dataStore, 'getResource', function() {
37 | var args = Array.prototype.slice.call(arguments);
38 | var href = args.shift();
39 | var callback = args.pop();
40 | callback(null, {href: href});
41 | });
42 |
43 | done();
44 | });
45 |
46 | after(function() {
47 | sandbox.restore();
48 | });
49 |
50 | it('should provide a getAccount method', function() {
51 | assert(typeof apiKey.getAccount === 'function');
52 | });
53 |
54 | describe('getAccount', function() {
55 | it('should return an Account object', function(done) {
56 | apiKey.getAccount(function(err, account) {
57 | if (err) {
58 | return done(err);
59 | }
60 |
61 | assert(account.href === '/boom');
62 | assert(getResourceStub.calledOnce);
63 |
64 | done();
65 | });
66 | });
67 | });
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/test/sp.resource.authenticationResult_test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var common = require('./common');
4 | var sinon = common.sinon;
5 | var assert = common.assert;
6 | var timekeeper = common.timekeeper;
7 |
8 | var Account = require('../lib/resource/Account');
9 | var AuthenticationResult = require('../lib/resource/AuthenticationResult');
10 | var DataStore = require('../lib/ds/DataStore');
11 |
12 | describe('Resources: ', function () {
13 | describe('Authentication Result resource', function () {
14 | var dataStore;
15 |
16 | before(function () {
17 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
18 | });
19 |
20 | describe('if ttl', function () {
21 | describe('isn\'t set', function () {
22 | it('should have a default value of 3600', function () {
23 | var result = new AuthenticationResult();
24 | assert.equal(result.ttl, 3600);
25 | });
26 | });
27 |
28 | describe('is set', function () {
29 | var app;
30 | var result;
31 |
32 | before(function () {
33 | app = {account: {href: 'boom!'}, dataStore: dataStore};
34 | result = new AuthenticationResult(app, dataStore);
35 |
36 | result.application = app;
37 | result.ttl = 9999;
38 | });
39 |
40 | it('should return jwt with specified ttl', function () {
41 | timekeeper.freeze(0);
42 |
43 | var jwt = result.getJwt();
44 | assert.equal(jwt.body.exp, new Date().getTime() + result.ttl);
45 |
46 | timekeeper.reset();
47 | });
48 | });
49 | });
50 |
51 | describe('get accounts', function () {
52 | describe('if accounts not set', function () {
53 | //var authcResult = new AuthenticationResult();
54 |
55 | //function getAccountsWithoutHref() {
56 | // authcResult.getAccount();
57 | //}
58 |
59 | //it('should throw unhandled exception', function () {
60 | // getAccountsWithoutHref.should
61 | // .throw(/cannot read property 'href' of undefined/i);
62 | //});
63 | });
64 |
65 | describe('if accounts are set', function () {
66 | var sandbox, authcResult, getResourceStub, cbSpy, app, opt;
67 | before(function () {
68 | sandbox = sinon.sandbox.create();
69 | app = {account: {href: 'boom!'}};
70 | opt = {};
71 | authcResult = new AuthenticationResult(app, dataStore);
72 | getResourceStub = sandbox.stub(dataStore, 'getResource', function (href, options, ctor, cb) {
73 | cb();
74 | });
75 | cbSpy = sandbox.spy();
76 |
77 | // call without optional param
78 | authcResult.getAccount(cbSpy);
79 | // call with optional param
80 | authcResult.getAccount(opt, cbSpy);
81 | });
82 | after(function () {
83 | sandbox.restore();
84 | });
85 |
86 | it('should get accounts', function () {
87 | /* jshint -W030 */
88 | getResourceStub.should.have.been.calledTwice;
89 | cbSpy.should.have.been.calledTwice;
90 | /* jshint +W030 */
91 |
92 | // call without optional param
93 | getResourceStub.should.have.been
94 | .calledWith(app.account.href, null, Account, cbSpy);
95 | // call with optional param
96 | getResourceStub.should.have.been
97 | .calledWith(app.account.href, opt, Account, cbSpy);
98 | });
99 | });
100 | });
101 | });
102 | });
103 |
--------------------------------------------------------------------------------
/test/sp.resource.factorInstantiator_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var common = require('./common');
4 | var assert = common.assert;
5 | var sinon = common.sinon;
6 |
7 | var InstanceResource = require('../lib/resource/InstanceResource');
8 | var FactorInstantiator = require('../lib/resource/FactorInstantiator');
9 | var FactorConstructor = FactorInstantiator.Constructor;
10 | var Factor = require('../lib/resource/Factor');
11 | var SmsFactor = require('../lib/resource/SmsFactor');
12 | var GoogleAuthenticatorFactor = require('../lib/resource/GoogleAuthenticatorFactor');
13 |
14 | describe('FactorInstantiator#Constructor', function() {
15 | var sandbox;
16 |
17 | before(function() {
18 | sandbox = sinon.sandbox.create();
19 | });
20 |
21 | after(function() {
22 | sandbox.restore();
23 | });
24 |
25 | it('should inherit from InstanceResource', function() {
26 | assert.equal(FactorConstructor.super_, InstanceResource);
27 | });
28 |
29 | it('should construct an SmsFactor if type is SMS', function() {
30 | assert.instanceOf(new FactorConstructor({type: 'SMS'}), SmsFactor);
31 | });
32 |
33 | it('should construct a GoogleAuthenticatorFactor if type is google-authenticator', function() {
34 | assert.instanceOf(new FactorConstructor({type: 'google-authenticator'}), GoogleAuthenticatorFactor);
35 | });
36 | });
37 |
38 | describe('FactorInstantiator#getConstructor', function() {
39 | var sandbox;
40 | var getConstructor;
41 |
42 | before(function() {
43 | sandbox = sinon.sandbox.create();
44 | getConstructor = FactorInstantiator.getConstructor;
45 | });
46 |
47 | after(function() {
48 | sandbox.restore();
49 | });
50 |
51 | it('should throw an error if called without any parameters', function() {
52 | assert.throws(getConstructor, Error, 'Factor instances must have a defined type');
53 | });
54 |
55 | it('should throw an error if called without a type parameter', function() {
56 | assert.throws(getConstructor.bind(null, {}), Error, 'Factor instances must have a defined type');
57 | });
58 |
59 | it('should return the base Factor type if called with an unknown type parameter', function() {
60 | assert.equal(getConstructor({type: 'foo'}), Factor);
61 | });
62 |
63 | it('should not throw an error if called with a valid type (sms or google-authenticator)', function() {
64 | assert.doesNotThrow(getConstructor.bind(null, {type: 'SMS'}), Error);
65 | assert.doesNotThrow(getConstructor.bind(null, {type: 'google-authenticator'}), Error);
66 | });
67 |
68 | it('should construct an SmsFactor if the type is `SMS`, regardless of capitalization', function() {
69 | assert.equal(getConstructor({type: 'sms'}), SmsFactor);
70 | assert.equal(getConstructor({type: 'SMS'}), SmsFactor);
71 | assert.equal(getConstructor({type: 'sMs'}), SmsFactor);
72 | });
73 |
74 | it('should construct an GoogleAuthenticatorFactor if the type is `google-authenticator`, regardless of capitalization', function() {
75 | assert.equal(getConstructor({type: 'google-authenticator'}), GoogleAuthenticatorFactor);
76 | assert.equal(getConstructor({type: 'GOOGLE-AUTHENTICATOR'}), GoogleAuthenticatorFactor);
77 | assert.equal(getConstructor({type: 'Google-Authenticator'}), GoogleAuthenticatorFactor);
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/test/sp.resource.field_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var common = require('./common');
4 | var sinon = common.sinon;
5 |
6 | var DataStore = require('../lib/ds/DataStore');
7 | var Field = require('../lib/resource/Field');
8 |
9 | describe('Field Resource', function () {
10 | describe('save()', function () {
11 | var sandbox;
12 | var field;
13 | var dataStore;
14 | var requestExecutorStub;
15 |
16 | var mockField = {
17 | href: 'https://api.stormpath.com/v1/fields/7dDfMOkrekkLhbWBLcGWuN',
18 | createdAt: '2016-08-02T20:16:21.931Z',
19 | modifiedAt: '2016-08-02T20:16:21.931Z',
20 | name: 'givenName',
21 | required: true,
22 | schema: {
23 | href: 'https://api.stormpath.com/v1/schemas/7dDfMLQmkARN4mQK9MPGIJ'
24 | }
25 | };
26 |
27 | before(function () {
28 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
29 | sandbox = sinon.sandbox.create();
30 | field = new Field(mockField, dataStore);
31 | requestExecutorStub = sandbox.stub(dataStore.requestExecutor, 'execute');
32 | });
33 |
34 | after(function () {
35 | sandbox.restore();
36 | });
37 |
38 | it('should post the resource to the REST API', function () {
39 | field.save();
40 | requestExecutorStub.should.have.been.calledWith({
41 | body: mockField,
42 | uri: mockField.href,
43 | method: 'POST'
44 | });
45 | });
46 | });
47 | });
--------------------------------------------------------------------------------
/test/sp.resource.googleAuthenticatorFactor_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var common = require('./common');
4 | var assert = common.assert;
5 | var sinon = common.sinon;
6 |
7 | var Factor = require('../lib/resource/Factor');
8 | var GoogleAuthenticatorFactor = require('../lib/resource/GoogleAuthenticatorFactor');
9 | var DataStore = require('../lib/ds/DataStore');
10 | var Challenge = require('../lib/resource/Challenge');
11 |
12 | var factorData = {
13 | href: 'https://api.stormpath.com/v1/factors/wzU29J38OcAyY1z8TeX1x',
14 | type: 'google-authenticator',
15 | createdAt: '2016-09-22T17:58:09.645Z',
16 | modifiedAt: '2016-09-22T17:58:09.646Z',
17 | status: 'ENABLED',
18 | verificationStatus: 'UNVERIFIED',
19 | account: {
20 | href: 'https://api.stormpath.com/v1/accounts/3apenYvL0Z9v9spexample'
21 | },
22 | challenges: {
23 | href: 'https://api.stormpath.com/v1/factors/wzU29J38OcAyY1z8TeX1x/challenges'
24 | },
25 | mostRecentChallenge: {
26 | href: 'https://api.stormpath.com/v1/challenges/wzYMCbEUJ5Nx4S7VRSMkX'
27 | }
28 | };
29 |
30 | describe('GoogleAuthenticatorFactor', function() {
31 | var dataStore;
32 | var factor;
33 | var superSpy;
34 | var createResourceStub;
35 |
36 | before(function() {
37 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
38 | superSpy = sinon.spy(GoogleAuthenticatorFactor, 'super_');
39 | factor = new GoogleAuthenticatorFactor(factorData, dataStore);
40 | createResourceStub = sinon.stub(dataStore, 'createResource');
41 | });
42 |
43 | it('should inherit from Factor', function() {
44 | assert.instanceOf(factor, Factor);
45 | });
46 |
47 | it('should call super_ with the same parameters', function() {
48 | superSpy.should.have.been.calledWithExactly(factorData, dataStore);
49 | });
50 |
51 | describe('GoogleAuthenticatorFactor#createChallenge', function() {
52 | var callback;
53 | var options = {};
54 |
55 | before(function() {
56 | callback = sinon.spy();
57 |
58 | factor.createChallenge(options, callback);
59 | });
60 |
61 | it('should call DataStore#createResource', function() {
62 | /*jshint -W030 */
63 | createResourceStub.should.have.been.calledOnce;
64 | /*jshint +W030 */
65 | });
66 |
67 | it('should pass the correct href to DataStore#createResource', function() {
68 | createResourceStub.args[0][0].should.equal(factorData.challenges.href);
69 | });
70 |
71 | it('should pass options to DataStore#createResource', function() {
72 | assert.equal(createResourceStub.args[0][1], options);
73 | });
74 |
75 | it('should not pass a request body to DataStore#createResource', function() {
76 | assert.isNull(createResourceStub.args[0][2]);
77 | });
78 |
79 | it('should pass the correct constructor to DataStore#createResource', function() {
80 | createResourceStub.args[0][3].should.equal(Challenge);
81 | });
82 |
83 | it('should pass the correct callback to DataStore#createResource', function() {
84 | createResourceStub.args[0][4].should.equal(callback);
85 | });
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/test/sp.resource.phone_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var common = require('./common');
4 | var assert = common.assert;
5 | var sinon = common.sinon;
6 |
7 | var InstanceResource = require('../lib/resource/InstanceResource');
8 | var DataStore = require('../lib/ds/DataStore');
9 | var Phone = require('../lib/resource/Phone');
10 | var Account = require('../lib/resource/Account');
11 |
12 | var phoneData = {
13 | href: 'https://api.stormpath.com/v1/phones/7lHGSpTvuxNnvnCkpOwUiR',
14 | createdAt: '2016-09-22T16:52:50.136Z',
15 | modifiedAt: '2016-09-22T16:52:50.136Z',
16 | number: '+12675555555',
17 | description: null,
18 | name: null,
19 | verificationStatus: 'UNVERIFIED',
20 | status: 'ENABLED',
21 | account: {
22 | href: 'https://api.stormpath.com/v1/accounts/3apenYvL0Z9v9spexaMple'
23 | }
24 | };
25 |
26 | describe('Phone resource', function() {
27 | var sandbox;
28 | var dataStore;
29 | var phone;
30 | var getResourceStub;
31 |
32 | before(function() {
33 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
34 | sandbox = sinon.sandbox.create();
35 | getResourceStub = sinon.stub(dataStore, 'getResource');
36 | phone = new Phone(phoneData, dataStore);
37 | });
38 |
39 | after(function() {
40 | sandbox.restore();
41 | });
42 |
43 | describe('constructor', function() {
44 | var superSpy;
45 |
46 | before(function() {
47 | superSpy = sandbox.spy(Phone, 'super_');
48 |
49 | new Phone(phoneData, dataStore);
50 | });
51 |
52 | it('should call super_ with the same arguments', function() {
53 | /*jshint -W030 */
54 | superSpy.should.have.been.calledOnce;
55 | superSpy.should.have.been.calledWithExactly(phoneData, dataStore);
56 | /*jshint +W030 */
57 | });
58 | });
59 |
60 | describe('instantiation and inheritance', function() {
61 | it('should inherit from InstanceResource', function() {
62 | assert.instanceOf(phone, InstanceResource);
63 | });
64 |
65 | it('should be an instance of Phone', function() {
66 | assert.instanceOf(phone, Phone);
67 | });
68 | });
69 |
70 | describe('#getAccount(options, callback)', function() {
71 | var callback;
72 |
73 | before(function() {
74 | callback = sinon.spy();
75 | phone.getAccount(callback);
76 | });
77 |
78 | it('should call dataStore#getResource', function() {
79 | /*jshint -W030 */
80 | getResourceStub.should.have.been.calledOnce;
81 | /*jshint +W030 */
82 | });
83 |
84 | it('should pass the correct href to dataStore#getResource', function() {
85 | getResourceStub.args[0][0].should.equal(phoneData.account.href);
86 | });
87 |
88 | it('should pass no options to dataStore#getResource', function() {
89 | /*jshint -W030 */
90 | getResourceStub.args[0][1].should.be.empty;
91 | /*jshint +W030 */
92 | });
93 |
94 | it('should pass the constructor for Account to dataStore#getResource', function() {
95 | getResourceStub.args[0][2].should.equal(Account);
96 | });
97 |
98 | it('should pass the callback to dataStore#getResource', function() {
99 | getResourceStub.args[0][3].should.equal(callback);
100 | });
101 | });
102 | });
103 |
--------------------------------------------------------------------------------
/test/sp.resource.resource_test.js:
--------------------------------------------------------------------------------
1 | var common = require('./common');
2 | var _ = common._;
3 | var should = common.should;
4 |
5 | var Resource = require('../lib/resource/Resource');
6 | var DataStore = require('../lib/ds/DataStore');
7 |
8 | describe('Resources: ', function () {
9 | describe('Resource base class', function () {
10 | describe('constructor', function () {
11 | var apiKey;
12 |
13 | before(function () {
14 | apiKey = {id: 'id', secret: 'secret'};
15 | });
16 |
17 | describe('if called with 2 params', function () {
18 | var resource, ds;
19 | var obj;
20 |
21 | before(function () {
22 | obj = {data: 'boom!', data2: 'boom2!'};
23 | ds = new DataStore({client: {apiKey:apiKey}});
24 | resource = new Resource(obj, ds);
25 | });
26 |
27 | it('should copy all fields from data', function () {
28 | _.each(obj, function (val, key) {
29 | resource[key].should.be.equal(val);
30 | });
31 | });
32 | it('should persist data store instance', function () {
33 | resource.dataStore.should.be.an.instanceof(DataStore);
34 | resource.dataStore.should.be.equal(ds);
35 | });
36 | });
37 |
38 | describe('if called only with data param', function () {
39 | var resource;
40 | var obj;
41 |
42 | before(function () {
43 | obj = {data: 'boom!', data2: 'boom2!'};
44 | resource = new Resource(obj);
45 | });
46 |
47 | it('should copy all fields from data param', function () {
48 | _.each(obj, function (val, key) {
49 | resource[key].should.be.equal(val);
50 | });
51 | });
52 | it('should leave dataStore empty', function(){
53 | should.not.exist(resource.dataStore);
54 | });
55 | });
56 |
57 | describe('if called only with data store param', function () {
58 | var resource, ds;
59 | var hack;
60 |
61 | before(function () {
62 | hack = 'boom!';
63 | ds = new DataStore({client: {apiKey:apiKey}});
64 | ds.hack = hack;
65 |
66 | resource = new Resource(ds);
67 | });
68 |
69 | it('should not copy any fields from data param', function(){
70 | should.not.exist(resource.hack);
71 | });
72 | it('should persist data store instance', function(){
73 | resource.dataStore.should.be.an.instanceof(DataStore);
74 | resource.dataStore.should.be.equal(ds);
75 | });
76 | });
77 | });
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/test/sp.resource.schema_test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var common = require('./common');
4 | var assert = common.assert;
5 | var sinon = common.sinon;
6 |
7 | var DataStore = require('../lib/ds/DataStore');
8 | var Field = require('../lib/resource/Field');
9 | var Schema = require('../lib/resource/Schema');
10 |
11 | describe('Schema Resource', function(){
12 |
13 | describe('getFields()', function(){
14 |
15 | var sandbox;
16 | var schema;
17 | var dataStore;
18 |
19 | var mockSchema = {
20 | href: 'https://api.stormpath.com/v1/schemas/7cvoYkLuGzpnAuVlKQdiDf/',
21 | fields: {
22 | href: 'https://api.stormpath.com/v1/schemas/7cvoYkLuGzpnAuVlKQdiDf/fields'
23 | }
24 | };
25 |
26 | var mockFieldsResponse = {
27 | href: 'https://api.stormpath.com/v1/schemas/7dDfMLQmkARN4mQK9MPGIJ/fields',
28 | offset: 0,
29 | limit: 25,
30 | size: 2,
31 | items: [
32 | {
33 | href: 'https://api.stormpath.com/v1/fields/7dDfMOkrekkLhbWBLcGWuN',
34 | createdAt: '2016-08-02T20:16:21.931Z',
35 | modifiedAt: '2016-08-02T20:16:21.931Z',
36 | name: 'givenName',
37 | required: true,
38 | schema: {
39 | href: 'https://api.stormpath.com/v1/schemas/7dDfMLQmkARN4mQK9MPGIJ'
40 | }
41 | },
42 | ]
43 | };
44 |
45 |
46 |
47 | before(function(){
48 | dataStore = new DataStore({client: {apiKey: {id: 1, secret: 2}}});
49 | sandbox = sinon.sandbox.create();
50 | schema = new Schema(mockSchema, dataStore);
51 |
52 | sandbox.stub(dataStore.requestExecutor, 'execute', function (req, cb) {
53 | cb(null, mockFieldsResponse);
54 | });
55 | });
56 |
57 | after(function(){
58 | sandbox.restore();
59 | });
60 |
61 | it('should return Field instances', function(done){
62 | schema.getFields(function(err, result){
63 | assert.equal(result.items, mockFieldsResponse.items);
64 | assert.instanceOf(mockFieldsResponse.items[0], Field);
65 | done();
66 | });
67 | });
68 | });
69 | });
--------------------------------------------------------------------------------