capcoauth 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -35
  3. data/.rspec +1 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +10 -0
  6. data/Gemfile.lock +171 -0
  7. data/README.md +3 -1
  8. data/Rakefile +7 -7
  9. data/app/controllers/capcoauth/application_controller.rb +8 -1
  10. data/app/controllers/capcoauth/login_controller.rb +5 -1
  11. data/app/controllers/capcoauth/logout_controller.rb +2 -6
  12. data/capcoauth.gemspec +13 -6
  13. data/lib/capcoauth/config.rb +52 -58
  14. data/lib/capcoauth/errors.rb +3 -0
  15. data/lib/capcoauth/notifications.rb +11 -9
  16. data/lib/capcoauth/oauth/access_token.rb +0 -1
  17. data/lib/capcoauth/oauth/token_verifier.rb +15 -10
  18. data/lib/capcoauth/rails/helpers.rb +45 -44
  19. data/lib/capcoauth/version.rb +11 -1
  20. data/lib/capcoauth.rb +1 -9
  21. data/lib/generators/capcoauth/templates/initializer.rb +23 -12
  22. data/spec/dummy/Rakefile +7 -0
  23. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  24. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  25. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  26. data/spec/dummy/app/controllers/metal_controller.rb +11 -0
  27. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  28. data/spec/dummy/app/models/user.rb +3 -0
  29. data/spec/dummy/app/views/home/index.html.erb +0 -0
  30. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/spec/dummy/config/application.rb +16 -0
  32. data/spec/dummy/config/boot.rb +6 -0
  33. data/spec/dummy/config/database.yml +15 -0
  34. data/spec/dummy/config/environment.rb +5 -0
  35. data/spec/dummy/config/environments/development.rb +29 -0
  36. data/spec/dummy/config/environments/production.rb +62 -0
  37. data/spec/dummy/config/environments/test.rb +42 -0
  38. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +6 -0
  39. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  40. data/spec/dummy/config/initializers/capcoauth.rb +41 -0
  41. data/spec/dummy/config/initializers/secret_token.rb +9 -0
  42. data/spec/dummy/config/initializers/session_store.rb +8 -0
  43. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  44. data/spec/dummy/config/routes.rb +50 -0
  45. data/spec/dummy/config.ru +4 -0
  46. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  47. data/spec/dummy/db/schema.rb +22 -0
  48. data/spec/dummy/public/404.html +26 -0
  49. data/spec/dummy/public/422.html +26 -0
  50. data/spec/dummy/public/500.html +26 -0
  51. data/spec/dummy/public/favicon.ico +0 -0
  52. data/spec/dummy/script/rails +6 -0
  53. data/spec/generators/install_generator_spec.rb +27 -0
  54. data/spec/generators/templates/routes.rb +3 -0
  55. data/spec/lib/capcoauth/oauth/access_token_spec.rb +31 -0
  56. data/spec/lib/capcoauth/oauth/token_verifier_spec.rb +121 -0
  57. data/spec/lib/capcoauth/oauth/ttl_cache_spec.rb +88 -0
  58. data/spec/lib/capcoauth_spec.rb +3 -0
  59. data/spec/lib/config_spec.rb +215 -0
  60. data/spec/lib/version_spec.rb +25 -0
  61. data/spec/spec_helper.rb +8 -0
  62. data/spec/spec_helper_integration.rb +50 -0
  63. data/spec/support/http_method_shim.rb +38 -0
  64. data/spec/support/orm/active_record.rb +3 -0
  65. metadata +172 -12
  66. data/lib/capcoauth/helpers/controller.rb +0 -15
@@ -0,0 +1,22 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended that you check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20111122132257) do
15
+
16
+ create_table "users", force: :cascade do |t|
17
+ t.string "name"
18
+ t.datetime "created_at"
19
+ t.datetime "updated_at"
20
+ end
21
+
22
+ end
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ <p>We've been notified about this issue and we'll take a look at it shortly.</p>
24
+ </div>
25
+ </body>
26
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,27 @@
1
+ require 'spec_helper_integration'
2
+ require 'generators/capcoauth/install_generator'
3
+
4
+ describe 'Capcoauth::InstallGenerator' do
5
+ include GeneratorSpec::TestCase
6
+
7
+ tests Capcoauth::InstallGenerator
8
+ destination ::File.expand_path('../tmp/dummy', __FILE__)
9
+
10
+ describe 'after running the generator' do
11
+ before :each do
12
+ prepare_destination
13
+ FileUtils.mkdir(::File.expand_path('config', Pathname(destination_root)))
14
+ FileUtils.mkdir(::File.expand_path('db', Pathname(destination_root)))
15
+ FileUtils.copy_file(::File.expand_path('../templates/routes.rb', __FILE__), ::File.expand_path('config/routes.rb', Pathname.new(destination_root)))
16
+ run_generator
17
+ end
18
+
19
+ it 'creates an initializer file' do
20
+ assert_file 'config/initializers/capcoauth.rb'
21
+ end
22
+
23
+ it 'adds sample route' do
24
+ assert_file 'config/routes.rb', /use_capcoauth/
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+
3
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Capcoauth::OAuth::AccessToken do
4
+
5
+ describe '.initialize' do
6
+ it 'has token but no user ID' do
7
+ token = Capcoauth::OAuth::AccessToken.new 'abc'
8
+ expect(token.token).to eq('abc')
9
+ expect(token.user_id).to be_nil
10
+ end
11
+
12
+ it 'calls TTLCache.user_id_for and sets user_id to return value' do
13
+ ttl_cache_double = class_double('Capcoauth::OAuth::TTLCache').as_stubbed_const
14
+ allow(ttl_cache_double).to receive(:user_id_for).and_return('123')
15
+ token = Capcoauth::OAuth::AccessToken.new 'abc'
16
+ expect(token.token).to eq('abc')
17
+ expect(token.user_id).to eq('123')
18
+ end
19
+ end
20
+
21
+ describe '.verify' do
22
+ it 'calls TokenVerifier.verify with self' do
23
+ verifier_double = class_double('Capcoauth::OAuth::TokenVerifier').as_stubbed_const
24
+ allow(verifier_double).to receive(:verify).and_return('CALLED')
25
+
26
+ token = Capcoauth::OAuth::AccessToken.new nil
27
+ expect(token.token).to be_nil
28
+ expect(token.verify).to eq('CALLED')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,121 @@
1
+ require 'httparty'
2
+ require 'net/http'
3
+
4
+ class MockHttpResponse
5
+ def initialize(**opts)
6
+ opts.each do |key, val|
7
+ instance_variable_set("@#{key}", val)
8
+ end
9
+ end
10
+ def code; @code; end
11
+ def headers; @headers; end
12
+ def parsed_response; @body; end
13
+ end
14
+
15
+ describe Capcoauth::OAuth::TokenVerifier do
16
+ subject { Capcoauth::OAuth::TokenVerifier }
17
+ describe '#verify' do
18
+ before do
19
+ Capcoauth.configuration.client_id = 'verifier_test_client_id'
20
+ end
21
+
22
+ it 'raises UnauthorizedError when no access token object passed' do
23
+ expect{subject.verify(nil)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Please log in to continue')
24
+ end
25
+
26
+ it 'raises UnauthorizedError when access token object has no token material' do
27
+ expect{subject.verify(Capcoauth::OAuth::AccessToken.new(nil))}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Please log in to continue')
28
+ end
29
+
30
+ it 'returns access token object if access_token is valid' do
31
+ Capcoauth::OAuth::TTLCache.update('abc', '123')
32
+ token = Capcoauth::OAuth::AccessToken.new('abc')
33
+ expect(subject.verify(token)).to equal(token)
34
+ Capcoauth::OAuth::TTLCache.remove('abc')
35
+ end
36
+
37
+ it 'calls HTTParty.get and raises OtherError on Net::OpenTimeout' do
38
+ httparty_double = class_double('HTTParty').as_stubbed_const
39
+ expect(httparty_double).to receive(:get).and_raise(Net::OpenTimeout)
40
+ token = Capcoauth::OAuth::AccessToken.new('iamnew')
41
+ expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::OtherError, 'An error occurred while verifying your credentials (server not available)')
42
+ end
43
+
44
+ it 'calls HTTParty.get and raises UnauthorizedError if ID type is not returned' do
45
+ Capcoauth.configuration.user_id_field = :psoft
46
+ httparty_double = class_double('HTTParty').as_stubbed_const
47
+ expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: {
48
+ 'resource_owner_id' => '123',
49
+ 'external_ids' => {}
50
+ }))
51
+ token = Capcoauth::OAuth::AccessToken.new('iamnew')
52
+ expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'The system cannot recognize you by that ID type')
53
+ Capcoauth.configuration.user_id_field = :capcoauth
54
+ end
55
+
56
+ it 'calls HTTParty.get and raises UnauthorizedError if ID type is not returned' do
57
+ httparty_double = class_double('HTTParty').as_stubbed_const
58
+ expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: {
59
+ 'resource_owner_id' => '123',
60
+ 'application' => {
61
+ 'uid' => 'not_client_id_123'
62
+ }
63
+ }))
64
+ token = Capcoauth::OAuth::AccessToken.new('iamnew')
65
+ expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Your credentials are valid, but are not for use with this system')
66
+ end
67
+
68
+ it 'calls HTTParty.get and raises UnauthorizedError if token is unknown' do
69
+ httparty_double = class_double('HTTParty').as_stubbed_const
70
+ expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 401, body: {
71
+ 'error': 'invalid_request',
72
+ 'error_description': 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
73
+ }))
74
+ token = Capcoauth::OAuth::AccessToken.new('iamnew')
75
+ expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Please log in to continue')
76
+ end
77
+
78
+ it 'calls HTTParty.get and raises UnauthorizedError if token is unknown' do
79
+ httparty_double = class_double('HTTParty').as_stubbed_const
80
+ expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 12345, body: {
81
+ 'error': 'invalid_request',
82
+ 'error_description': 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
83
+ }))
84
+ token = Capcoauth::OAuth::AccessToken.new('iamnew')
85
+ expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::OtherError, 'An error occurred while verifying your credentials (unknown response)')
86
+ end
87
+
88
+ it 'calls HTTParty.get and returns access token with capcoauth id type' do
89
+ httparty_double = class_double('HTTParty').as_stubbed_const
90
+ expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: {
91
+ 'resource_owner_id' => 'capcoauth_123',
92
+ 'application' => {
93
+ 'uid' => 'verifier_test_client_id'
94
+ }
95
+ }))
96
+ token = Capcoauth::OAuth::AccessToken.new('capcoauth_user_token')
97
+ expect(subject.verify(token)).to equal(token)
98
+ expect(token.user_id).to eq('capcoauth_123')
99
+ Capcoauth::OAuth::TTLCache.remove('capcoauth_user_token')
100
+ end
101
+
102
+ it 'calls HTTParty.get and returns access token with psoft id type' do
103
+ Capcoauth.configuration.user_id_field = :psoft
104
+ httparty_double = class_double('HTTParty').as_stubbed_const
105
+ expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: {
106
+ 'resource_owner_id' => '123',
107
+ 'application' => {
108
+ 'uid' => 'verifier_test_client_id'
109
+ },
110
+ 'external_ids' => {
111
+ 'psoft' => 'psoft_123'
112
+ }
113
+ }))
114
+ token = Capcoauth::OAuth::AccessToken.new('psoft_user_token')
115
+ expect(subject.verify(token)).to equal(token)
116
+ expect(token.user_id).to eq('psoft_123')
117
+ Capcoauth::OAuth::TTLCache.remove('psoft_user_token')
118
+ Capcoauth.configuration.user_id_field = :capcoauth
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Capcoauth::OAuth::TTLCache do
4
+ subject { Capcoauth::OAuth::TTLCache }
5
+
6
+ describe '#user_id_for' do
7
+ it 'returns nil when store contains no token' do
8
+ expect(subject.user_id_for('idontexist')).to be_nil
9
+ end
10
+
11
+ it 'returns user_id when store contains token' do
12
+ subject.update('abc', '123')
13
+ expect(subject.user_id_for('abc')).to eq('123')
14
+ subject.remove('abc')
15
+ end
16
+
17
+ it 'returns user_id when TTL is almost expired' do
18
+ subject.update('abc', '123')
19
+ Timecop.freeze(Time.zone.now + (Capcoauth.configuration.token_verify_ttl - 1).seconds) do
20
+ expect(subject.user_id_for('abc')).to eq('123')
21
+ end
22
+ subject.remove('abc')
23
+ end
24
+
25
+ it 'returns nil when TTL is expired' do
26
+ subject.update('abc', '123')
27
+ Timecop.freeze(Time.zone.now + (Capcoauth.configuration.token_verify_ttl + 1).seconds) do
28
+ expect(subject.user_id_for('abc')).to be_nil
29
+ end
30
+ subject.remove('abc')
31
+ end
32
+ end
33
+
34
+ describe '#update' do
35
+ it 'returns true on write' do
36
+ expect(subject.update('abc', '123')).to be true
37
+ expect(subject.user_id_for('abc')).to eq('123')
38
+ subject.remove('abc')
39
+ end
40
+
41
+ it 'respects expires_in TTL' do
42
+ subject.update('abc', '123')
43
+ Timecop.freeze(Time.zone.now + (Capcoauth.configuration.token_verify_ttl - 1).seconds) do
44
+ expect(subject.user_id_for('abc')).to eq('123')
45
+ end
46
+ Timecop.freeze(Time.zone.now + (Capcoauth.configuration.token_verify_ttl + 1).seconds) do
47
+ expect(subject.user_id_for('abc')).to be_nil
48
+ end
49
+ subject.remove('abc')
50
+ end
51
+
52
+ it 'overwrites existing values' do
53
+ subject.update('abc', '123')
54
+ expect(subject.update('abc', '456')).to be true
55
+ expect(subject.user_id_for('abc')).to eq('456')
56
+ subject.remove('abc')
57
+ end
58
+ end
59
+
60
+ describe '#remove' do
61
+ it 'returns false when value doesn\'t exist' do
62
+ expect(subject.remove('idontexist')).to be false
63
+ end
64
+ it 'returns true when value exists' do
65
+ expect(subject.update('abc', '123')).to be true
66
+ expect(subject.remove('abc')).to be true
67
+ end
68
+ it 'returns true when value is expired and false after removed' do
69
+ expect(subject.update('abc', '123')).to be true
70
+ Timecop.freeze(Time.zone.now + (Capcoauth.configuration.token_verify_ttl + 1).seconds) do
71
+ expect(subject.remove('abc')).to be true
72
+ expect(subject.remove('abc')).to be false
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '#key_for' do
78
+ it 'returns formatted key' do
79
+ expect(subject.key_for('abc')).to eq('capcoauth_token:abc')
80
+ end
81
+ end
82
+
83
+ describe '#store' do
84
+ it 'returns Capcoauth.cache_store' do
85
+ expect(subject.store).to equal(Capcoauth.configuration.cache_store)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,3 @@
1
+ require 'spec_helper'
2
+ describe Capcoauth do
3
+ end
@@ -0,0 +1,215 @@
1
+ require 'spec_helper_integration'
2
+
3
+ class DummyLogger; end
4
+ class DummyStore; end
5
+ class DummyUser
6
+ attr_reader :user_id
7
+ def initialize(user_id)
8
+ @user_id = user_id
9
+ end
10
+ end
11
+
12
+ describe Capcoauth::Config do
13
+ subject {
14
+ Capcoauth.configure do |config|
15
+ config.client_id = 'ci'
16
+ config.client_secret = 'cs'
17
+ config.user_resolver = -> user_id {
18
+ DummyUser.new user_id
19
+ }
20
+ end
21
+ }
22
+
23
+ describe 'subject' do
24
+ it 'is an instance of Capcoauth::Config' do
25
+ expect(subject).to be_a(Capcoauth::Config)
26
+ end
27
+ end
28
+
29
+ describe 'default config requires required options' do
30
+ subject :default_config do
31
+ Capcoauth::Config::Builder.new do; end.build
32
+ end
33
+
34
+ it 'fails when not client_id not set' do
35
+ expect{default_config.client_id}.to raise_error(Capcoauth::MissingRequiredOptionError, 'Missing required option `client_id`')
36
+ end
37
+ it 'fails when not client_secret not set' do
38
+ expect{default_config.client_secret}.to raise_error(Capcoauth::MissingRequiredOptionError, 'Missing required option `client_secret`')
39
+ end
40
+ it 'fails when not client_user_resolver not set' do
41
+ expect{default_config.user_resolver}.to raise_error(Capcoauth::MissingRequiredOptionError, 'Missing required option/lambda `user_resolver`')
42
+ end
43
+ end
44
+
45
+ describe 'client_id' do
46
+ it 'has value of ci' do
47
+ expect(subject.client_id).to eq('ci')
48
+ end
49
+ it 'can be updated to test_123' do
50
+ subject.client_id = 'test_123'
51
+ expect(subject.client_id).to eq('test_123')
52
+ subject.client_id = 'ci'
53
+ end
54
+ it 'cannot be set to nil' do
55
+ expect{subject.client_id = nil}.to raise_error(Capcoauth::MissingRequiredOptionError, '`client_id` cannot be set to nil')
56
+ end
57
+ end
58
+
59
+ describe 'client_secret' do
60
+ it 'has value of cs' do
61
+ expect(subject.client_secret).to eq('cs')
62
+ end
63
+ it 'can be updated to test_123' do
64
+ subject.client_secret = 'test_456'
65
+ expect(subject.client_secret).to eq('test_456')
66
+ subject.client_secret = 'cs'
67
+ end
68
+ it 'cannot be set to nil' do
69
+ expect{subject.client_secret = nil}.to raise_error(Capcoauth::MissingRequiredOptionError, '`client_secret` cannot be set to nil')
70
+ end
71
+ end
72
+
73
+ describe 'user_resolver' do
74
+ before do
75
+ @old_resolver = subject.user_resolver
76
+ end
77
+ after do
78
+ subject.user_resolver = @old_resolver
79
+ end
80
+
81
+ it 'sets the block that is accessible via user_resolver' do
82
+ block = proc {}
83
+ subject.user_resolver = block
84
+ expect(subject.user_resolver).to equal(block)
85
+ end
86
+
87
+ it 'returns a dummy user' do
88
+ returned_user = subject.user_resolver.call('123')
89
+ expect(returned_user).to be_a(DummyUser)
90
+ expect(returned_user.user_id).to eq('123')
91
+ end
92
+
93
+ it 'raises error from resolver' do
94
+ subject.user_resolver = -> user_id {
95
+ User.find_by! id: user_id
96
+ }
97
+ expect{subject.user_resolver.call('iwillneverexist')}.to raise_error(ActiveRecord::RecordNotFound, 'Couldn\'t find User')
98
+ end
99
+ end
100
+
101
+ describe 'logger' do
102
+ after do
103
+ subject.logger = ::Rails.logger
104
+ end
105
+
106
+ it 'defaults to Rails.logger' do
107
+ expect(subject.logger).to equal(::Rails.logger)
108
+ end
109
+ it 'can be updated to custom logger' do
110
+ new_logger = DummyLogger.new
111
+ subject.logger = new_logger
112
+ expect(subject.logger).to equal(new_logger)
113
+ end
114
+ it 'can be set to nil' do
115
+ subject.logger = nil
116
+ expect(subject.logger).to be_nil
117
+ end
118
+ end
119
+
120
+ describe 'using_routes' do
121
+ it 'has value false by default' do
122
+ expect(subject.using_routes).to be_falsey
123
+ end
124
+ it 'can be updated to true' do
125
+ subject.using_routes = true
126
+ expect(subject.using_routes).to be_truthy
127
+ subject.using_routes = false
128
+ end
129
+ it 'is updated to true by Rails.application.routes.draw' do
130
+ subject.using_routes = false
131
+ expect(subject.using_routes).to be_falsy
132
+ Rails.application.routes.draw do
133
+ use_capcoauth
134
+ end
135
+ expect(subject.using_routes).to be_truthy
136
+ end
137
+ end
138
+
139
+ describe 'perform_login_redirects' do
140
+ it 'has value true by default' do
141
+ expect(subject.perform_login_redirects).to be_truthy
142
+ end
143
+ it 'can be updated to false' do
144
+ subject.perform_login_redirects = false
145
+ expect(subject.perform_login_redirects).to be_falsey
146
+ subject.perform_login_redirects = true
147
+ end
148
+ end
149
+
150
+ describe 'token_verify_ttl' do
151
+ it 'has value 10 by default' do
152
+ expect(subject.token_verify_ttl).to eq(Capcoauth::Config::TOKEN_VERIFY_TTL_DEFAULT)
153
+ end
154
+ it 'can be updated to other value' do
155
+ subject.token_verify_ttl = 60
156
+ expect(subject.token_verify_ttl).to eq(60)
157
+ subject.token_verify_ttl = Capcoauth::Config::TOKEN_VERIFY_TTL_DEFAULT
158
+ end
159
+ end
160
+
161
+ describe 'capcoauth_url' do
162
+ it "has value #{Capcoauth::Config::CAPCOAUTH_URL_DEFAULT} by default" do
163
+ expect(subject.capcoauth_url).to eq(Capcoauth::Config::CAPCOAUTH_URL_DEFAULT)
164
+ end
165
+ it 'can be updated to other value' do
166
+ subject.capcoauth_url = 'https://example.com'
167
+ expect(subject.capcoauth_url).to eq('https://example.com')
168
+ subject.capcoauth_url = Capcoauth::Config::CAPCOAUTH_URL_DEFAULT
169
+ end
170
+ end
171
+
172
+ describe 'user_id_field' do
173
+ it 'has value :capcoauth by default' do
174
+ expect(subject.user_id_field).to eq(:capcoauth)
175
+ end
176
+ it 'can be updated to false' do
177
+ subject.user_id_field = :psoft
178
+ expect(subject.user_id_field).to eq(:psoft)
179
+ subject.user_id_field = :capcoauth
180
+ end
181
+ end
182
+
183
+ describe 'cache_store' do
184
+ before do
185
+ @cache_store = subject.cache_store
186
+ end
187
+ after do
188
+ subject.cache_store = @cache_store
189
+ end
190
+
191
+ it 'defaults to ActiveSupport::Cache::MemoryStore store' do
192
+ expect(subject.cache_store).to be_a(::ActiveSupport::Cache::MemoryStore)
193
+ end
194
+ it 'can be updated to custom store' do
195
+ new_store = DummyStore.new
196
+ subject.cache_store = new_store
197
+ expect(subject.cache_store).to equal(new_store)
198
+ end
199
+ it 'can be set to nil' do
200
+ subject.cache_store = nil
201
+ expect(subject.cache_store).to be_nil
202
+ end
203
+ end
204
+
205
+ describe 'require_user' do
206
+ it 'has value true by default' do
207
+ expect(subject.require_user).to be_truthy
208
+ end
209
+ it 'can be updated to false' do
210
+ subject.require_user = false
211
+ expect(subject.require_user).to be_falsey
212
+ subject.require_user = true
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ describe Capcoauth do
3
+ describe '#gem_version' do
4
+ subject { Capcoauth.gem_version }
5
+
6
+ it 'has a Gem::Version version' do
7
+ expect(subject).to be_a(Gem::Version)
8
+ end
9
+ it 'has semver format' do
10
+ parts = subject.to_s.split('.')
11
+ expect(parts.length).to eq(3)
12
+ parts.each do |part|
13
+ expect(part.to_i.to_s).to eq(part)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ describe Capcoauth::VERSION do
20
+ it 'has integer parts' do
21
+ expect(Capcoauth::VERSION::MAJOR).to be_an(Integer)
22
+ expect(Capcoauth::VERSION::MINOR).to be_an(Integer)
23
+ expect(Capcoauth::VERSION::PATCH).to be_an(Integer)
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ # $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../lib'))
2
+ # $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../app'))
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start 'rails'
6
+
7
+ require 'rails'
8
+ require 'capcoauth'