From 89cb397c7aa15cf67d26426352dc1a44e7e560f2 Mon Sep 17 00:00:00 2001 From: Emre Unal Date: Wed, 6 Jan 2016 02:17:56 +0200 Subject: [PATCH] Add blueprints for authorizers and authenticators --- .npmignore | 1 + .travis.yml | 2 +- blueprints/.jshintrc | 7 ++ .../files/__root__/authenticators/__name__.js | 4 + blueprints/authenticator/index.js | 54 +++++++++++ .../files/__root__/authorizers/__name__.js | 4 + blueprints/authorizer/index.js | 39 ++++++++ node-tests/blueprints/authenticator-test.js | 93 +++++++++++++++++++ node-tests/blueprints/authorizer-test.js | 69 ++++++++++++++ node-tests/nodetest-runner.js | 70 ++++++++++++++ package.json | 12 ++- 11 files changed, 352 insertions(+), 3 deletions(-) create mode 100644 blueprints/.jshintrc create mode 100644 blueprints/authenticator/files/__root__/authenticators/__name__.js create mode 100644 blueprints/authenticator/index.js create mode 100644 blueprints/authorizer/files/__root__/authorizers/__name__.js create mode 100644 blueprints/authorizer/index.js create mode 100644 node-tests/blueprints/authenticator-test.js create mode 100644 node-tests/blueprints/authorizer-test.js create mode 100644 node-tests/nodetest-runner.js diff --git a/.npmignore b/.npmignore index d522ca2b7..204e58a4c 100644 --- a/.npmignore +++ b/.npmignore @@ -13,3 +13,4 @@ bower.json ember-cli-build.js Brocfile.js testem.json +node-tests diff --git a/.travis.yml b/.travis.yml index a4330bb98..d10754641 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ install: - bower install script: - - ember try $EMBER_TRY_SCENARIO test + - ember try $EMBER_TRY_SCENARIO test && npm run nodetest notifications: email: false diff --git a/blueprints/.jshintrc b/blueprints/.jshintrc new file mode 100644 index 000000000..345543677 --- /dev/null +++ b/blueprints/.jshintrc @@ -0,0 +1,7 @@ +{ + "predef": [ + "console" + ], + "strict": false, + "node": true +} diff --git a/blueprints/authenticator/files/__root__/authenticators/__name__.js b/blueprints/authenticator/files/__root__/authenticators/__name__.js new file mode 100644 index 000000000..de755b2e0 --- /dev/null +++ b/blueprints/authenticator/files/__root__/authenticators/__name__.js @@ -0,0 +1,4 @@ +<%= imports %> + +export default <%= baseClass %>.extend({<%= body %> +}); diff --git a/blueprints/authenticator/index.js b/blueprints/authenticator/index.js new file mode 100644 index 000000000..85992e65c --- /dev/null +++ b/blueprints/authenticator/index.js @@ -0,0 +1,54 @@ +var EOL = require('os').EOL; +var SilentError = require('silent-error'); +var isPackageMissing = require('ember-cli-is-package-missing'); + +module.exports = { + description: 'Generates an Ember Simple Auth authenticator', + + availableOptions: [ + { name: 'base-class', type: String, values: ['oauth2', 'devise', 'torii', 'base'], default: 'base' } + ], + + locals: function(options) { + var name = options.entity.name; + var baseClass = options.baseClass || 'base'; + + if (baseClass === 'torii') { + return { + imports: 'import Ember from \'ember\';' + EOL + 'import Torii from \'ember-simple-auth/authenticators/torii\';', + baseClass: 'Torii', + body: EOL + ' torii: Ember.inject.service(\'torii\')' + }; + } else if (baseClass === 'oauth2') { + return { + imports: 'import Ember from \'ember\';' + EOL + 'import OAuth2PasswordGrant from \'ember-simple-auth/authenticators/oauth2-password-grant\';', + baseClass: 'OAuth2PasswordGrant', + body: '' + }; + } else if (baseClass === 'devise') { + return { + imports: 'import Ember from \'ember\';' + EOL + 'import Devise from \'ember-simple-auth/authenticators/devise\';', + baseClass: 'Devise', + body: '' + }; + } else if (baseClass === 'base') { + return { + imports: 'import Ember from \'ember\';' + EOL + 'import Base from \'ember-simple-auth/authenticators/base\';', + baseClass: 'Base', + body: EOL + ' restore(data) {' + EOL + ' },' + EOL + EOL + ' authenticate(/*args*/) {' + EOL + ' },' + EOL + EOL + ' invalidate(data) {' + EOL + ' }' + }; + } else if (name === baseClass) { + throw new SilentError('Authenticators cannot extend from themself. Remove the --base-class option or specify one of "oauth2", "torii" or "devise".'); + } else { + throw new SilentError('The authenticator base class "' + baseClass + '" is unknown. Remove the --base-class option or specify one of "oauth2", "torii" or "devise".'); + } + }, + + afterInstall: function(options) { + if (!options.dryRun && options.torii && isPackageMissing(this, 'torii')) { + return this.addPackagesToProject([ + { name: 'torii', target: '~0.6.1' } + ]); + } + } +}; diff --git a/blueprints/authorizer/files/__root__/authorizers/__name__.js b/blueprints/authorizer/files/__root__/authorizers/__name__.js new file mode 100644 index 000000000..de755b2e0 --- /dev/null +++ b/blueprints/authorizer/files/__root__/authorizers/__name__.js @@ -0,0 +1,4 @@ +<%= imports %> + +export default <%= baseClass %>.extend({<%= body %> +}); diff --git a/blueprints/authorizer/index.js b/blueprints/authorizer/index.js new file mode 100644 index 000000000..4c75eddd1 --- /dev/null +++ b/blueprints/authorizer/index.js @@ -0,0 +1,39 @@ +var EOL = require('os').EOL; +var SilentError = require('silent-error'); + +module.exports = { + description: 'Generates an Ember Simple Auth authorizer', + + availableOptions: [ + { name: 'base-class', type: String, values: ['oauth2', 'devise', 'base'], default: 'base' } + ], + + locals: function(options) { + var name = options.entity.name; + var baseClass = options.baseClass || 'base'; + + if (baseClass === 'oauth2') { + return { + imports: 'import OAuth2Bearer from \'ember-simple-auth/authorizers/oauth2-bearer\';', + baseClass: 'OAuth2Bearer', + body: '' + }; + } else if (baseClass === 'devise') { + return { + imports: 'import Devise from \'ember-simple-auth/authorizers/devise\';', + baseClass: 'Devise', + body: '' + }; + } else if (baseClass === 'base') { + return { + imports: 'import Base from \'ember-simple-auth/authorizers/base\';', + baseClass: 'Base', + body: EOL + ' authorize(/*data, block*/) {' + EOL + ' }' + }; + } else if (name === baseClass) { + throw new SilentError('Authorizers cannot extend from themself. Remove the --base-class option or specify one of "oauth2" or "devise".'); + } else { + throw new SilentError('The authorizer base class "' + baseClass + '" is unknown. Remove the --base-class option or specify one of "oauth2" or "devise".'); + } + } +}; diff --git a/node-tests/blueprints/authenticator-test.js b/node-tests/blueprints/authenticator-test.js new file mode 100644 index 000000000..e61b97ad4 --- /dev/null +++ b/node-tests/blueprints/authenticator-test.js @@ -0,0 +1,93 @@ +'use strict'; + +var EOL = require('os').EOL; +var setupTestHooks = require('ember-cli-blueprint-test-helpers/lib/helpers/setup'); +var BlueprintHelpers = require('ember-cli-blueprint-test-helpers/lib/helpers/blueprint-helper'); +var generateAndDestroy = BlueprintHelpers.generateAndDestroy; + +describe('Acceptance: ember generate and destroy authenticator', function() { + setupTestHooks(this); + + it('generates a torii authenticator', function() { + return generateAndDestroy(['authenticator', 'application', '--base-class=torii'], { + files: [ + { file: 'app/authenticators/application.js', contains: ['\ +import Ember from \'ember\';' + EOL + '\ +import Torii from \'ember-simple-auth/authenticators/torii\';' + EOL + '\ +' + EOL + '\ +export default Torii.extend({' + EOL + '\ + torii: Ember.inject.service(\'torii\')' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('generates an OAuth 2.0 authenticator', function() { + return generateAndDestroy(['authenticator', 'application', '--base-class=oauth2'], { + files: [ + { file: 'app/authenticators/application.js', contains: ['\ +import Ember from \'ember\';' + EOL + '\ +import OAuth2PasswordGrant from \'ember-simple-auth/authenticators/oauth2-password-grant\';' + EOL + '\ +' + EOL + '\ +export default OAuth2PasswordGrant.extend({' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('generates a devise authenticator', function() { + return generateAndDestroy(['authenticator', 'application', '--base-class=devise'], { + files: [ + { file: 'app/authenticators/application.js', contains: ['\ +import Ember from \'ember\';' + EOL + '\ +import Devise from \'ember-simple-auth/authenticators/devise\';' + EOL + '\ +' + EOL + '\ +export default Devise.extend({' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('generates a generic authenticator', function() { + return generateAndDestroy(['authenticator', 'application'], { + files: [ + { file: 'app/authenticators/application.js', contains: ['\ +import Ember from \'ember\';' + EOL + '\ +import Base from \'ember-simple-auth/authenticators/base\';' + EOL + '\ +' + EOL + '\ +export default Base.extend({' + EOL + '\ + restore(data) {' + EOL + '\ + },' + EOL + '\ +' + EOL + '\ + authenticate(/*args*/) {' + EOL + '\ + },' + EOL + '\ +' + EOL + '\ + invalidate(data) {' + EOL + '\ + }' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('throws when the authenticator is specified as its own base class', function() { + return generateAndDestroy(['authenticator', 'application', '--base-class=application'], { + throws: { + message: 'Authenticators cannot extend from themself. Remove the --base-class option or specify one of "oauth2", "torii" or "devise".', + type: 'SilentError' + } + }); + }); + + it('throws when an unknown base class is specified', function() { + return generateAndDestroy(['authenticator', 'application', '--base-class=unknown'], { + throws: { + message: 'The authenticator base class "unknown" is unknown. Remove the --base-class option or specify one of "oauth2", "torii" or "devise".', + type: 'SilentError' + } + }); + }); +}); diff --git a/node-tests/blueprints/authorizer-test.js b/node-tests/blueprints/authorizer-test.js new file mode 100644 index 000000000..9a1246664 --- /dev/null +++ b/node-tests/blueprints/authorizer-test.js @@ -0,0 +1,69 @@ +'use strict'; + +var EOL = require('os').EOL; +var setupTestHooks = require('ember-cli-blueprint-test-helpers/lib/helpers/setup'); +var BlueprintHelpers = require('ember-cli-blueprint-test-helpers/lib/helpers/blueprint-helper'); +var generateAndDestroy = BlueprintHelpers.generateAndDestroy; + +describe('Acceptance: ember generate and destroy authorizer', function() { + setupTestHooks(this); + + it('generates an OAuth 2.0 authorizer', function() { + return generateAndDestroy(['authorizer', 'application', '--base-class=oauth2'], { + files: [ + { file: 'app/authorizers/application.js', contains: ['\ +import OAuth2Bearer from \'ember-simple-auth/authorizers/oauth2-bearer\';' + EOL + '\ +' + EOL + '\ +export default OAuth2Bearer.extend({' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('generates a devise authorizer', function() { + return generateAndDestroy(['authorizer', 'application', '--base-class=devise'], { + files: [ + { file: 'app/authorizers/application.js', contains: ['\ +import Devise from \'ember-simple-auth/authorizers/devise\';' + EOL + '\ +' + EOL + '\ +export default Devise.extend({' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('generates a generic authorizer', function() { + return generateAndDestroy(['authorizer', 'application'], { + files: [ + { file: 'app/authorizers/application.js', contains: ['\ +import Base from \'ember-simple-auth/authorizers/base\';' + EOL + '\ +' + EOL + '\ +export default Base.extend({' + EOL + '\ + authorize(/*data, block*/) {' + EOL + '\ + }' + EOL + '\ +});' + EOL + '\ +']} + ] + }); + }); + + it('throws when the authorizer is specified as its own base class', function() { + return generateAndDestroy(['authorizer', 'application', '--base-class=application'], { + throws: { + message: 'Authorizers cannot extend from themself. Remove the --base-class option or specify one of "oauth2" or "devise".', + type: 'SilentError' + } + }); + }); + + it('throws when an unknown base class is specified', function() { + return generateAndDestroy(['authorizer', 'application', '--base-class=unknown'], { + throws: { + message: 'The authorizer base class "unknown" is unknown. Remove the --base-class option or specify one of "oauth2" or "devise".', + type: 'SilentError' + } + }); + }); +}); diff --git a/node-tests/nodetest-runner.js b/node-tests/nodetest-runner.js new file mode 100644 index 000000000..968a150f2 --- /dev/null +++ b/node-tests/nodetest-runner.js @@ -0,0 +1,70 @@ +'use strict'; + +var glob = require('glob'); +var Mocha = require('mocha'); +var Promise = require('ember-cli/lib/ext/promise'); +var rimraf = require('rimraf'); +var mochaOnlyDetector = require('mocha-only-detector'); + +if (process.env.EOLNEWLINE) { + require('os').EOL = '\n'; +} + +rimraf.sync('.node_modules-tmp'); +rimraf.sync('.bower_components-tmp'); + +var root = 'node-tests/{blueprints,acceptance,unit}'; +var _checkOnlyInTests = Promise.denodeify(mochaOnlyDetector.checkFolder.bind(null, root + '/**/*{-test}.js')); +var optionOrFile = process.argv[2]; +var mocha = new Mocha({ + timeout: 5000, + reporter: 'spec' +}); +var testFiles = glob.sync(root + '/**/*-test.js'); + +if (optionOrFile === 'all') { + addFiles(mocha, testFiles); + addFiles(mocha, 'node-tests/**/*-test.js'); + addFiles(mocha, '/**/*-test-slow.js'); +} else if (process.argv.length > 2) { + addFiles(mocha, process.argv.slice(2)); +} else { + addFiles(mocha, testFiles); +} + +function addFiles(mocha, files) { + files = (typeof files === 'string') ? glob.sync(root + files) : files; + files.forEach(mocha.addFile.bind(mocha)); +} + +function checkOnlyInTests() { + console.log('Verifing `.only` in tests'); + return _checkOnlyInTests().then(function() { + console.log('No `.only` found'); + }); +} + +function runMocha() { + mocha.run(function(failures) { + process.on('exit', function() { + process.exit(failures); + }); + }); +} + +function ciVerificationStep() { + if (process.env.CI === 'true') { + return checkOnlyInTests(); + } else { + return Promise.resolve(); + } +} + +ciVerificationStep() + .then(function() { + runMocha(); + }) + .catch(function(error) { + console.error(error); + process.exit(1); + }); diff --git a/package.json b/package.json index 3ea17e246..0b5e2da30 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "scripts": { "build": "ember build", "start": "ember server", - "test": "ember try:testall" + "test": "ember try:testall", + "nodetest": "node node-tests/nodetest-runner.js" }, "repository": "https://github.com/simplabs/ember-simple-auth", "engines": { @@ -26,21 +27,24 @@ "ember-cli": "1.13.13", "ember-cli-app-version": "^1.0.0", "ember-cli-base64": "~0.0.1", + "ember-cli-blueprint-test-helpers": "0.7.0", "ember-cli-content-security-policy": "0.4.0", "ember-cli-dependency-checker": "^1.1.0", "ember-cli-htmlbars": "^1.0.1", "ember-cli-htmlbars-inline-precompile": "^0.3.1", "ember-cli-ic-ajax": "0.2.4", "ember-cli-inject-live-reload": "^1.3.1", + "ember-cli-internal-test-helpers": "^0.5.0", "ember-cli-mocha": "~0.9.7", + "ember-cli-is-package-missing": "^1.0.0", "ember-cli-pretender": "~0.5.0", "ember-cli-release": "0.2.8", "ember-cli-sri": "^1.2.0", "ember-cli-uglify": "^1.2.0", "ember-data": "~2.2.0", + "ember-disable-prototype-extensions": "^1.0.0", "ember-disable-proxy-controllers": "^1.0.1", "ember-export-application-global": "^1.0.4", - "ember-disable-prototype-extensions": "^1.0.0", "ember-sinon": "~0.3.0", "ember-suave": "~1.2.2", "ember-try": "~0.0.8", @@ -50,7 +54,11 @@ "handlebars": "~3.0.3", "lodash": "^3.10.1", "marked": "^0.3.5", + "mocha": "^2.4.5", + "mocha-only-detector": "0.0.2", "morgan": "^1.5.2", + "rimraf": "^2.3.2", + "silent-error": "^1.0.0", "sinon-chai": "~2.8.0", "torii": "~0.6.1" },