capcoauth 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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'