g5_authenticatable 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a62091f31bef8d7d3b0dbd2b57aa2e3dc627ebc
4
- data.tar.gz: e74855a8c9bf2e5e89edf97d40cb4d11ba004427
3
+ metadata.gz: 01d16764300ca8cf106601e9bc00625631f1feb0
4
+ data.tar.gz: bba2757fa2298839be4230713b1804adde562198
5
5
  SHA512:
6
- metadata.gz: b815696a057a7e20ff3a0d6e67fe831ac69c8f17663a8419039b501e76da81fef1ab7cd3122fdbbe6166504f46ad943df072be16ed89d80945a24a908c568194
7
- data.tar.gz: 077e3c67efa60753a0333cb6a749c0e7066a07605737a9148af854a819a532781a32effc1f7f9c51ee81920fef946136552e1765a84845d36bc6854d3d4837ef
6
+ metadata.gz: 776f2f806c5f29953799728e93503f5947424b426f64f45283b750f290dddbaecece6015c9d2d6acf0b77e3110714b6849ccf5f1754fd3d113deb857dfe8b12c
7
+ data.tar.gz: 30d6470860d0f7c0a504ca37d056133a9ed44eb57bebc33a0d2630e2078da0432ce80bb5d31f0402f78577ab4719dcbcf4501e699e2c7e926da4616c232c650e
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.1.2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## v0.4.0 (2015-01-20)
2
+
3
+ * Several fixes around sign-out, including accepting GET requests and
4
+ enabling strict token validation
5
+ ([#21](https://github.com/G5/g5_authenticatable/pull/21))
6
+ * Improved documentation around controller test helpers
7
+ ([#22](https://github.com/G5/g5_authenticatable/pull/22))
8
+ * Added `g5_authenticatable:purge_users` rake task to purge local user data;
9
+ primarily used for configuring demo/dev environments built on a production
10
+ clone or DB dump
11
+ ([#23](https://github.com/G5/g5_authenticatable/pull/23))
12
+
1
13
  ## v0.3.0 (2014-03-13)
2
14
 
3
15
  * First open source release to [RubyGems](https://rubygems.org)
@@ -17,7 +29,7 @@
17
29
 
18
30
  ## v0.1.2 (2014-03-05)
19
31
 
20
- * Set G5_AUTH_USERNAME and G5_AUTH_PASSWORD on auth client defaults
32
+ * Set `G5_AUTH_USERNAME` and `G5_AUTH_PASSWORD` on auth client defaults
21
33
 
22
34
  ## v0.1.0 (2014-02-26)
23
35
 
data/Gemfile CHANGED
@@ -6,13 +6,13 @@ source 'https://rubygems.org'
6
6
  gemspec
7
7
 
8
8
  # Gems used by the dummy application
9
- gem 'rails', '~> 4.0.2'
9
+ gem 'rails', '4.1.4'
10
10
  gem 'jquery-rails'
11
11
  gem 'pg'
12
12
  gem 'grape'
13
13
 
14
14
  group :test, :development do
15
- gem 'rspec-rails', '~> 2.14'
15
+ gem 'rspec-rails', '~> 2.99'
16
16
  gem 'pry'
17
17
  gem 'dotenv-rails'
18
18
  end
@@ -23,7 +23,7 @@ group :test do
23
23
  gem 'simplecov', require: false
24
24
  gem 'codeclimate-test-reporter', require: false
25
25
  gem 'webmock'
26
- gem 'shoulda-matchers'
26
+ gem 'shoulda-matchers', '~> 2.6'
27
27
  gem 'generator_spec'
28
28
  gem 'rspec-http', require: 'rspec/http'
29
29
  end
data/README.md CHANGED
@@ -18,7 +18,7 @@ library in isolation.
18
18
 
19
19
  ## Current Version
20
20
 
21
- 0.3.0
21
+ 0.4.0
22
22
 
23
23
  ## Requirements
24
24
 
@@ -85,7 +85,7 @@ root :to => 'home#index'
85
85
  For non-production environments, this redirect URI does not have to
86
86
  be publicly accessible, but it must be accessible from the browser
87
87
  where you will be testing (so using something like
88
- http://localhost:3000/users/auth/g5/callback is fine if your browser
88
+ http://localhost:3000/g5_auth/users/auth/g5/callback is fine if your browser
89
89
  and client application server are both local).
90
90
 
91
91
  If you are using the production G5 Auth server, the redirect URI **MUST**
@@ -103,13 +103,31 @@ environment variables for your client application:
103
103
  * `G5_AUTH_CLIENT_ID` - the OAuth 2.0 application ID from the auth server
104
104
  * `G5_AUTH_CLIENT_SECRET` - the OAuth 2.0 application secret from the auth server
105
105
  * `G5_AUTH_REDIRECT_URI` - the OAuth 2.0 redirect URI registered with the auth server
106
- * `G5_AUTH_ENDPOINT` - the endpoint URL for the G5 auth server
106
+ * `G5_AUTH_ENDPOINT` - the endpoint URL (without any path info) for the G5 auth server.
107
+ Generally, this will be set to either `https://dev-auth.g5search.com` or
108
+ `https://auth.g5search.com` (the default).
107
109
 
108
- You can also set up a default user's credentials with:
110
+ If you need to make server-to-server API calls that are not associated with an
111
+ end user, you can also set up a default user's credentials with:
109
112
 
110
113
  * `G5_AUTH_USERNAME` - the G5 auth server user name
111
114
  * `G5_AUTH_PASSWORD` - the G5 auth server user's password
112
115
 
116
+ ### Token validation
117
+
118
+ By default, G5 Authenticatable only validates access tokens on incoming API
119
+ requests. If you are relying on session-based authentication instead, it is
120
+ possible for the local application's session to remain active after the
121
+ global access token has been revoked.
122
+
123
+ If you want to guarantee that the local session is destroyed when the access
124
+ token is revoked, add the following to
125
+ `config/initializers/g5_authenticatable.rb`:
126
+
127
+ ```ruby
128
+ G5Authenticatable.strict_token_validation = true
129
+ ```
130
+
113
131
  ## Usage
114
132
 
115
133
  ### Controller filters and helpers
@@ -255,6 +273,32 @@ following line in your `spec/spec_helper.rb`:
255
273
  require 'g5_authenticatable/rspec'
256
274
  ```
257
275
 
276
+ Note that the example code assumes you are using Rspec 3 metadata syntax. If you are
277
+ using Rspec 2.x, you can either:
278
+
279
+ * Enable this syntax with the following config in your `spec/spec_helper.rb`:
280
+
281
+ ```ruby
282
+ RSpec.configure do |config|
283
+ config.treat_symbols_as_metadata_keys_with_true_values = true
284
+ end
285
+ ```
286
+
287
+ * Or you can replace every instance of a bare symbol in the metadata with a full
288
+ key-value pair. For example:
289
+
290
+ ```ruby
291
+ # This won't work out of the box with Rspec 2
292
+ context 'my secure context', :auth do
293
+ it 'can see my secrets'
294
+ end
295
+
296
+ # But this will...
297
+ context 'my secure context', auth: true do
298
+ it 'can see my secrets'
299
+ end
300
+ ```
301
+
258
302
  #### Feature Specs ####
259
303
 
260
304
  The easiest way to use g5_authenticatable in feature specs is through
@@ -360,23 +404,40 @@ To use the shared context, tag your example group with the `:auth_controller`
360
404
  Rspec metadata:
361
405
 
362
406
  ```ruby
363
- describe 'my secure action', :auth_controller do
407
+ describe 'my secure action' do
364
408
  context 'when the user is authenticated' do
365
- it 'can access some secure path' do
366
- get :my_action
367
- expect(response). to be_success
368
- end
409
+ it 'can access some secure path' do
410
+ get :my_action
411
+ expect(response). to be_success
412
+ end
369
413
  end
370
414
 
371
- context 'whent there is no authenticated user' do
372
- it 'cannot access the secure path' do
373
- get :my_action
374
- expect(reponse).to be_redirect
375
- end
415
+ context 'when there is no authenticated user', :auth_controller do
416
+ it 'cannot access the secure path' do
417
+ get :my_action
418
+ expect(reponse).to be_redirect
419
+ end
376
420
  end
377
421
  end
378
422
  ```
379
423
 
424
+ ### Purging local user data
425
+
426
+ G5 Authenticatable automatically maintains user data locally via the
427
+ `G5Authenticatable::User` model. This local data can be purged
428
+ using the following rake task:
429
+
430
+ ```console
431
+ $ rake g5_authenticatable:purge_users
432
+ ```
433
+
434
+ Executing this task does not affect any remote user data on the
435
+ auth server.
436
+
437
+ It is especially important to purge the local user data
438
+ when reconfiguring a client application to use a different auth endpoint
439
+ (for example, when cloning a demo environment from production).
440
+
380
441
  ## Examples
381
442
 
382
443
  ### Protecting a particular Rails controller action
@@ -404,11 +465,10 @@ In your view template, add the following:
404
465
 
405
466
  ### Adding a link to sign out
406
467
 
407
- In order to sign out, the link must not only have the correct path,
408
- but must also use the DELETE HTTP method:
468
+ In your view template, add the following:
409
469
 
410
470
  ```html+erb
411
- <%= link_to('Logout', destroy_session_path(:user), :method => :delete) %>
471
+ <%= link_to('Logout', destroy_session_path(:user)) %>
412
472
  ```
413
473
 
414
474
  ### Selectively securing Grape API methods
@@ -460,6 +520,29 @@ In the code above, we assume that HTML requests come from a client that
460
520
  can display the auth server's sign in page to the end user, while all other
461
521
  formats are assumed to be API requests.
462
522
 
523
+ If HTML requests do not imply a client capable of providing a user to interact with
524
+ a signup form, you can try something like this:
525
+
526
+ ```ruby
527
+ class MyMixedUpController < ApplicationController
528
+ before_filter :authenticate_api_user!, if: :is_api_request?
529
+ before_filter :authenticate_user!, unless: :is_api_request?
530
+
531
+ respond_to :html
532
+
533
+ def show
534
+ resource = MyResource.find(params[:id])
535
+ respond_with(resource)
536
+ end
537
+
538
+ private
539
+
540
+ def is_api_request?
541
+ !G5Authenticatable::TokenValidator.new(params, headers).access_token.nil?
542
+ end
543
+ end
544
+ ```
545
+
463
546
  ## Authors
464
547
 
465
548
  * Maeve Revels / [@maeve](https://github.com/maeve)
@@ -19,5 +19,9 @@ module G5Authenticatable
19
19
  def after_omniauth_failure_path_for(scope)
20
20
  auth_error_path
21
21
  end
22
+
23
+ def after_sign_out_path_for(resource_or_scope)
24
+ main_app.root_path
25
+ end
22
26
  end
23
27
  end
data/circle.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  database:
2
2
  override:
3
3
  - cp spec/dummy/config/database.yml.ci spec/dummy/config/database.yml
4
- - RAILS_ENV=test rake app:db:setup
4
+ - RAILS_ENV=test bundle exec rake app:db:setup
@@ -222,7 +222,7 @@ Devise.setup do |config|
222
222
  # config.navigational_formats = ['*/*', :html]
223
223
 
224
224
  # The default HTTP method used to sign out a resource. Default is :delete.
225
- config.sign_out_via = :delete
225
+ config.sign_out_via = :get
226
226
 
227
227
  # ==> OmniAuth
228
228
  # Add a new OmniAuth provider. Check the wiki for more information on setting
data/config/routes.rb CHANGED
@@ -2,5 +2,10 @@ G5Authenticatable::Engine.routes.draw do
2
2
  devise_for :users, class_name: 'G5Authenticatable::User',
3
3
  module: :devise,
4
4
  controllers: {sessions: 'g5_authenticatable/sessions'}
5
+
6
+ devise_scope :user do
7
+ delete '/users/sign_out', to: redirect('users/sign_out')
8
+ end
9
+
5
10
  get '/auth_error', to: 'error#auth_error'
6
11
  end
@@ -20,6 +20,6 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
21
  spec.require_paths = ['lib']
22
22
 
23
- spec.add_dependency 'devise_g5_authenticatable', '~> 0.1'
24
- spec.add_dependency 'g5_authenticatable_api', '~> 0.2'
23
+ spec.add_dependency 'devise_g5_authenticatable', '~> 0.2'
24
+ spec.add_dependency 'g5_authenticatable_api', '~> 0.3.1'
25
25
  end
@@ -1,4 +1,5 @@
1
1
  require 'g5_authenticatable/test/factory'
2
+ require 'g5_authenticatable/test/token_validation_helpers'
2
3
  require 'g5_authenticatable/test/feature_helpers'
3
4
  require 'g5_authenticatable/test/request_helpers'
4
5
  require 'g5_authenticatable/test/controller_helpers'
@@ -16,6 +16,7 @@ module G5Authenticatable
16
16
 
17
17
  def visit_path_and_login_with(path, user)
18
18
  stub_g5_omniauth(user)
19
+ stub_valid_access_token(user.g5_access_token)
19
20
  visit path
20
21
  end
21
22
  end
@@ -19,7 +19,16 @@ shared_context 'auth request', auth_request: true do
19
19
 
20
20
  let(:user) { FactoryGirl.create(:g5_authenticatable_user) }
21
21
 
22
- before { login_user(user) }
22
+ let!(:orig_auth_endpoint) { ENV['G5_AUTH_ENDPOINT'] }
23
+ let(:auth_endpoint) { 'https://test.auth.host' }
24
+ before { ENV['G5_AUTH_ENDPOINT'] = auth_endpoint }
25
+ after { ENV['G5_AUTH_ENDPOINT'] = orig_auth_endpoint }
26
+
27
+ before do
28
+ login_user(user)
29
+ stub_valid_access_token(user.g5_access_token)
30
+ end
31
+
23
32
  after { logout_user }
24
33
  end
25
34
 
@@ -0,0 +1,25 @@
1
+ module G5Authenticatable
2
+ module Test
3
+ module TokenValidationHelpers
4
+ def stub_valid_access_token(token_value)
5
+ stub_request(:get, "#{ENV['G5_AUTH_ENDPOINT']}/oauth/token/info").
6
+ with(headers: {'Authorization'=>"Bearer #{token_value}"}).
7
+ to_return(status: 200, body: '', headers: {})
8
+ end
9
+
10
+ def stub_invalid_access_token(token_value)
11
+ stub_request(:get, "#{ENV['G5_AUTH_ENDPOINT']}/oauth/token/info").
12
+ with(headers: {'Authorization'=>"Bearer #{token_value}"}).
13
+ to_return(status: 401,
14
+ headers: {'Content-Type' => 'application/json; charset=utf-8',
15
+ 'Cache-Control' => 'no-cache'},
16
+ body: {'error' => 'invalid_token',
17
+ 'error_description' => 'The access token expired'}.to_json)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ RSpec.configure do |config|
24
+ config.include G5Authenticatable::Test::TokenValidationHelpers
25
+ end
@@ -1,3 +1,3 @@
1
1
  module G5Authenticatable
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -4,4 +4,16 @@ require 'devise_g5_authenticatable'
4
4
  require 'g5_authenticatable_api'
5
5
 
6
6
  module G5Authenticatable
7
+ # When enabled, access tokens are always validated against the auth
8
+ # server, even when that token is associated with an authenticated user.
9
+ # Disabled by default, meaning that tokens are only validated if
10
+ # they are explicitly passed in on an API request.
11
+ @@strict_token_validation = false
12
+ mattr_reader :strict_token_validation
13
+
14
+ def self.strict_token_validation=(validate)
15
+ @@strict_token_validation =
16
+ G5AuthenticatableApi.strict_token_validation =
17
+ Devise.g5_strict_token_validation = validate
18
+ end
7
19
  end
@@ -17,4 +17,8 @@ class G5Authenticatable::InstallGenerator < Rails::Generators::Base
17
17
  def mount_engine
18
18
  route "mount G5Authenticatable::Engine => '/g5_auth'"
19
19
  end
20
+
21
+ def create_initializer
22
+ template 'g5_authenticatable.rb', 'config/initializers/g5_authenticatable.rb'
23
+ end
20
24
  end
@@ -0,0 +1,8 @@
1
+ # Enable strict token validation to guarantee that an authenticated
2
+ # user's access token is still valid on the global auth server, at the
3
+ # cost of performance. When disabled, the user's access token will
4
+ # not be repeatedly validated, but this means that the local
5
+ # session may persist long after the access token is revoked on the
6
+ # auth server. Disabled by default.
7
+ #
8
+ # G5Authenticatable.strict_token_validation = true
@@ -0,0 +1,6 @@
1
+ namespace :g5_authenticatable do
2
+ desc 'Purge local user data from the DB'
3
+ task :purge_users do
4
+ G5Authenticatable::User.destroy_all
5
+ end
6
+ end
@@ -10,6 +10,7 @@
10
10
  <p class="notice"><%= notice %></p>
11
11
  <p class="alert"><%= alert %></p>
12
12
  <%= link_to('Login', new_session_path(:user)) %>
13
+ <%= link_to('Logout', destroy_session_path(:user)) %>
13
14
  <%= yield %>
14
15
 
15
16
  </body>
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'UI Token validation' do
4
+ let!(:old_auth_endpoint) { ENV['G5_AUTH_ENDPOINT'] }
5
+ before { ENV['G5_AUTH_ENDPOINT'] = auth_endpoint }
6
+ after { ENV['G5_AUTH_ENDPOINT'] = old_auth_endpoint }
7
+ let(:auth_endpoint) { 'https://auth.test.host' }
8
+
9
+ let(:user) { FactoryGirl.create(:g5_authenticatable_user) }
10
+
11
+ before do
12
+ stub_g5_omniauth(user)
13
+ visit protected_page_path
14
+
15
+ # Now that we're logged in, any subsequent attempts to
16
+ # authenticate with the auth server will trigger an omniauth
17
+ # failure, which is a condition we can test for
18
+ stub_g5_invalid_credentials
19
+ end
20
+
21
+ context 'when token validation is enabled' do
22
+ before { G5Authenticatable.strict_token_validation = true }
23
+
24
+ context 'when user has a valid g5 access token' do
25
+ before { stub_valid_access_token(user.g5_access_token) }
26
+
27
+ it 'should allow the user to visit a protected page' do
28
+ visit protected_page_path
29
+ expect(current_path).to eq(protected_page_path)
30
+ end
31
+ end
32
+
33
+ context 'when user has an invalid g5 access token' do
34
+ before { stub_invalid_access_token(user.g5_access_token) }
35
+
36
+ it 'should force the user to re-authenticate' do
37
+ visit protected_page_path
38
+ expect(current_path).to_not eq(protected_page_path)
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'when token validation is disabled' do
44
+ before { G5Authenticatable.strict_token_validation = false }
45
+
46
+ it 'should allow the user to visit a protected page' do
47
+ visit protected_page_path
48
+ expect(current_path).to eq(protected_page_path)
49
+ end
50
+ end
51
+ end
@@ -7,7 +7,7 @@ require 'spec_helper'
7
7
  require 'generators/g5_authenticatable/install/install_generator'
8
8
 
9
9
  describe G5Authenticatable::InstallGenerator, type: :generator do
10
- destination File.expand_path('../../../tmp', __FILE__)
10
+ destination File.expand_path('../../../../tmp', __FILE__)
11
11
 
12
12
  before do
13
13
  prepare_destination
@@ -27,6 +27,18 @@ describe G5Authenticatable::InstallGenerator, type: :generator do
27
27
  }
28
28
  end
29
29
 
30
+ it 'should copy the initializer' do
31
+ expect(destination_root).to have_structure {
32
+ directory 'config' do
33
+ directory 'initializers' do
34
+ file 'g5_authenticatable.rb' do
35
+ contains '# G5Authenticatable.strict_token_validation = true'
36
+ end
37
+ end
38
+ end
39
+ }
40
+ end
41
+
30
42
  it 'should mount the engine' do
31
43
  expect(destination_root).to have_structure {
32
44
  directory 'config' do
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ # Normally, we'd do this as a feature spec, but there's
4
+ # currently no easy way to get capybara to play along nicely
5
+ # with mocks for external redirects (the capybara-mechanize driver
6
+ # comes closest, but not quite)
7
+ describe 'Signing out' do
8
+ before { ENV['G5_AUTH_ENDPOINT'] = auth_endpoint }
9
+ after { ENV['G5_AUTH_ENDPOINT'] = nil }
10
+ let(:auth_endpoint) { 'https://auth.test.host' }
11
+
12
+ let(:auth_sign_out_url) do
13
+ "#{auth_endpoint}/users/sign_out?redirect_url=http%3A%2F%2Fwww.example.com%2F"
14
+ end
15
+
16
+ describe 'GET /g5_auth/users/sign_out' do
17
+ subject(:sign_out) { get '/g5_auth/users/sign_out' }
18
+
19
+ context 'when user is logged in', :auth_request do
20
+ it 'should redirect to the auth server' do
21
+ expect(sign_out).to redirect_to(auth_sign_out_url)
22
+ end
23
+
24
+ it 'should not allow the user to access protected pages' do
25
+ sign_out
26
+ expect(get '/protected_page').to redirect_to('/g5_auth/users/sign_in')
27
+ end
28
+ end
29
+
30
+ context 'when user is not logged in' do
31
+ it 'should redirect to the auth server' do
32
+ expect(sign_out).to redirect_to(auth_sign_out_url)
33
+ end
34
+ end
35
+ end
36
+
37
+ describe 'DELETE /g5_auth/users/sign_out', :auth_request do
38
+ subject(:sign_out) { delete '/g5_auth/users/sign_out' }
39
+
40
+ it 'should redirect to GET' do
41
+ expect(sign_out).to redirect_to('/g5_auth/users/sign_out')
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'API Token validation' do
4
+ let!(:old_auth_endpoint) { ENV['G5_AUTH_ENDPOINT'] }
5
+ before { ENV['G5_AUTH_ENDPOINT'] = auth_endpoint }
6
+ after { ENV['G5_AUTH_ENDPOINT'] = old_auth_endpoint }
7
+ let(:auth_endpoint) { 'https://auth.test.host' }
8
+
9
+ let(:token_info_url) { URI.join(auth_endpoint, '/oauth/token/info') }
10
+
11
+ let(:user) { FactoryGirl.create(:g5_authenticatable_user) }
12
+ before { login_user(user) }
13
+ after { logout_user }
14
+
15
+ subject(:api_call) { get '/rails_api/secure_resource.json' }
16
+
17
+ context 'when token validation is enabled' do
18
+ before { G5Authenticatable.strict_token_validation = true }
19
+
20
+ context 'when user has a valid g5 access token' do
21
+ before { stub_valid_access_token(user.g5_access_token) }
22
+
23
+ it 'should allow the user to make the api call' do
24
+ api_call
25
+ expect(response).to be_success
26
+ end
27
+ end
28
+
29
+ context 'when user has an invalid g5 access token' do
30
+ before { stub_invalid_access_token(user.g5_access_token) }
31
+
32
+ it 'should return a 401' do
33
+ api_call
34
+ expect(response).to be_http_unauthorized
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'when token validation is disabled' do
40
+ before { G5Authenticatable.strict_token_validation = false }
41
+
42
+ it 'should allow the user to make the api call' do
43
+ api_call
44
+ expect(response).to be_success
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Sign out routes' do
4
+ routes {G5Authenticatable::Engine.routes}
5
+
6
+ it 'should route GET /g5_auth/users/sign_out' do
7
+ expect(get('/users/sign_out')).to route_to(controller: 'g5_authenticatable/sessions',
8
+ action: 'destroy')
9
+ end
10
+ end
data/spec/spec_helper.rb CHANGED
@@ -48,5 +48,7 @@ RSpec.configure do |config|
48
48
 
49
49
  config.treat_symbols_as_metadata_keys_with_true_values = true
50
50
 
51
+ config.infer_spec_type_from_file_location!
52
+
51
53
  config.after(:suite) { WebMock.disable! }
52
54
  end
@@ -0,0 +1,21 @@
1
+ # Based on: http://robots.thoughtbot.com/test-rake-tasks-like-a-boss
2
+ # Modified for a non-Rails environment
3
+ require 'rake'
4
+
5
+ shared_context 'rake' do
6
+ let(:rake) { Rake::Application.new }
7
+ let(:task_name) { self.class.top_level_description }
8
+ let(:task_path) { "lib/tasks/#{task_name.split(':').first}/#{task_name.split(':').last}" }
9
+ let(:root_path) { File.expand_path('../../../..', __FILE__) }
10
+ subject(:task) { rake[task_name] }
11
+
12
+ def loaded_files_excluding_current_rake_file
13
+ $".reject {|file| file =~ /#{task_path}\.rake$/ }
14
+ end
15
+
16
+ before do
17
+ Rake.application = rake
18
+ Rake.application.rake_require(task_path, [root_path], loaded_files_excluding_current_rake_file)
19
+ Rake::Task.define_task(:environment)
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.before(:each) { G5Authenticatable.strict_token_validation = false }
3
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'g5_authenticatable:purge_users' do
4
+ include_context 'rake'
5
+
6
+ context 'when there are no local users' do
7
+ it 'should not raise any errors' do
8
+ expect { task.invoke }.to_not raise_error
9
+ end
10
+
11
+ it 'should not leave any user data in the db' do
12
+ task.invoke
13
+ expect(G5Authenticatable::User.count).to eq(0)
14
+ end
15
+ end
16
+
17
+ context 'when there is one local user' do
18
+ let!(:user) { FactoryGirl.create(:g5_authenticatable_user) }
19
+
20
+ it 'should delete the user data from the db' do
21
+ expect { task.invoke }.to change { G5Authenticatable::User.count }.from(1).to(0)
22
+ end
23
+ end
24
+
25
+ context 'when there are multiple local users' do
26
+ let!(:user1) { FactoryGirl.create(:g5_authenticatable_user) }
27
+ let!(:user2) { FactoryGirl.create(:g5_authenticatable_user) }
28
+
29
+ it 'should delete the user data from the db' do
30
+ expect { task.invoke }.to change { G5Authenticatable::User.count }.from(2).to(0)
31
+ end
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: g5_authenticatable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - maeve
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-13 00:00:00.000000000 Z
11
+ date: 2015-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise_g5_authenticatable
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.1'
19
+ version: '0.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.1'
26
+ version: '0.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: g5_authenticatable_api
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.2'
33
+ version: 0.3.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.2'
40
+ version: 0.3.1
41
41
  description: |-
42
42
  An engine that provides a basic User model,
43
43
  authentication logic, and remote credential
@@ -79,11 +79,13 @@ files:
79
79
  - lib/g5_authenticatable/test/factory.rb
80
80
  - lib/g5_authenticatable/test/feature_helpers.rb
81
81
  - lib/g5_authenticatable/test/request_helpers.rb
82
+ - lib/g5_authenticatable/test/token_validation_helpers.rb
82
83
  - lib/g5_authenticatable/version.rb
83
84
  - lib/generators/g5_authenticatable/install/USAGE
84
85
  - lib/generators/g5_authenticatable/install/install_generator.rb
85
86
  - lib/generators/g5_authenticatable/install/templates/create_g5_authenticatable_users.rb
86
- - lib/tasks/g5_authenticatable_tasks.rake
87
+ - lib/generators/g5_authenticatable/install/templates/g5_authenticatable.rb
88
+ - lib/tasks/g5_authenticatable/purge_users.rake
87
89
  - script/rails
88
90
  - spec/config/application_spec.rb
89
91
  - spec/controllers/.gitkeep
@@ -131,15 +133,22 @@ files:
131
133
  - spec/dummy/script/rails
132
134
  - spec/features/auth_error_path_spec.rb
133
135
  - spec/features/sign_in_spec.rb
136
+ - spec/features/token_validation_spec.rb
134
137
  - spec/g5_authenticatable/version_spec.rb
135
138
  - spec/lib/generators/g5_authenticatable/install_generator_spec.rb
136
139
  - spec/models/.gitkeep
137
140
  - spec/models/g5_authenticatable/user_spec.rb
138
141
  - spec/requests/grape_api_spec.rb
139
142
  - spec/requests/rails_api_spec.rb
143
+ - spec/requests/sign_out_spec.rb
144
+ - spec/requests/token_validation_spec.rb
140
145
  - spec/routing/auth_error_routing_spec.rb
146
+ - spec/routing/sign_out_routing_spec.rb
141
147
  - spec/spec_helper.rb
142
148
  - spec/support/devise.rb
149
+ - spec/support/shared_contexts/rake.rb
150
+ - spec/support/token_validation.rb
151
+ - spec/tasks/purge_users_spec.rb
143
152
  homepage: https://github.com/G5/g5_authenticatable
144
153
  licenses:
145
154
  - MIT
@@ -160,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
169
  version: '0'
161
170
  requirements: []
162
171
  rubyforge_project:
163
- rubygems_version: 2.2.0
172
+ rubygems_version: 2.2.2
164
173
  signing_key:
165
174
  specification_version: 4
166
175
  summary: An authentication engine for G5 applications.
@@ -211,12 +220,19 @@ test_files:
211
220
  - spec/dummy/script/rails
212
221
  - spec/features/auth_error_path_spec.rb
213
222
  - spec/features/sign_in_spec.rb
223
+ - spec/features/token_validation_spec.rb
214
224
  - spec/g5_authenticatable/version_spec.rb
215
225
  - spec/lib/generators/g5_authenticatable/install_generator_spec.rb
216
226
  - spec/models/.gitkeep
217
227
  - spec/models/g5_authenticatable/user_spec.rb
218
228
  - spec/requests/grape_api_spec.rb
219
229
  - spec/requests/rails_api_spec.rb
230
+ - spec/requests/sign_out_spec.rb
231
+ - spec/requests/token_validation_spec.rb
220
232
  - spec/routing/auth_error_routing_spec.rb
233
+ - spec/routing/sign_out_routing_spec.rb
221
234
  - spec/spec_helper.rb
222
235
  - spec/support/devise.rb
236
+ - spec/support/shared_contexts/rake.rb
237
+ - spec/support/token_validation.rb
238
+ - spec/tasks/purge_users_spec.rb
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :g5_authenticatable do
3
- # # Task goes here
4
- # end