doorkeeper 5.2.6 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +2 -2
  3. data/CHANGELOG.md +15 -14
  4. data/Gemfile +2 -2
  5. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  6. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
  7. data/app/controllers/doorkeeper/applications_controller.rb +3 -3
  8. data/app/controllers/doorkeeper/authorizations_controller.rb +2 -2
  9. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  10. data/gemfiles/rails_5_0.gemfile +2 -2
  11. data/gemfiles/rails_5_1.gemfile +2 -2
  12. data/gemfiles/rails_5_2.gemfile +2 -2
  13. data/gemfiles/rails_6_0.gemfile +2 -2
  14. data/gemfiles/rails_master.gemfile +2 -2
  15. data/lib/doorkeeper.rb +2 -3
  16. data/lib/doorkeeper/config.rb +71 -39
  17. data/lib/doorkeeper/grape/helpers.rb +1 -1
  18. data/lib/doorkeeper/helpers/controller.rb +10 -8
  19. data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
  20. data/lib/doorkeeper/models/access_token_mixin.rb +55 -18
  21. data/lib/doorkeeper/models/application_mixin.rb +3 -3
  22. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  23. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  24. data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
  25. data/lib/doorkeeper/oauth/authorization/code.rb +4 -4
  26. data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
  27. data/lib/doorkeeper/oauth/authorization_code_request.rb +13 -6
  28. data/lib/doorkeeper/oauth/base_request.rb +8 -4
  29. data/lib/doorkeeper/oauth/client.rb +7 -8
  30. data/lib/doorkeeper/oauth/client_credentials/creator.rb +16 -9
  31. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
  32. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +4 -4
  33. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  34. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  35. data/lib/doorkeeper/oauth/error.rb +1 -1
  36. data/lib/doorkeeper/oauth/error_response.rb +5 -5
  37. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
  38. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  39. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -1
  40. data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
  41. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
  42. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -3
  43. data/lib/doorkeeper/oauth/pre_authorization.rb +7 -5
  44. data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -5
  45. data/lib/doorkeeper/oauth/token.rb +2 -2
  46. data/lib/doorkeeper/oauth/token_introspection.rb +6 -6
  47. data/lib/doorkeeper/orm/active_record.rb +3 -3
  48. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  49. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  50. data/lib/doorkeeper/orm/active_record/application.rb +3 -155
  51. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
  52. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
  53. data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
  54. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +3 -3
  55. data/lib/doorkeeper/rails/helpers.rb +4 -4
  56. data/lib/doorkeeper/rails/routes.rb +5 -7
  57. data/lib/doorkeeper/rake/db.rake +3 -3
  58. data/lib/doorkeeper/request.rb +1 -1
  59. data/lib/doorkeeper/request/authorization_code.rb +3 -3
  60. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  61. data/lib/doorkeeper/request/password.rb +2 -2
  62. data/lib/doorkeeper/request/refresh_token.rb +3 -3
  63. data/lib/doorkeeper/server.rb +1 -1
  64. data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
  65. data/lib/doorkeeper/version.rb +2 -2
  66. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  67. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  68. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  69. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  70. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
  71. data/lib/generators/doorkeeper/templates/initializer.rb +39 -8
  72. data/spec/controllers/application_metal_controller_spec.rb +1 -1
  73. data/spec/controllers/applications_controller_spec.rb +3 -2
  74. data/spec/controllers/authorizations_controller_spec.rb +18 -18
  75. data/spec/controllers/protected_resources_controller_spec.rb +25 -17
  76. data/spec/controllers/token_info_controller_spec.rb +1 -1
  77. data/spec/controllers/tokens_controller_spec.rb +1 -1
  78. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
  79. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
  80. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
  81. data/spec/generators/install_generator_spec.rb +1 -1
  82. data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
  83. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  84. data/spec/lib/config_spec.rb +61 -21
  85. data/spec/lib/doorkeeper_spec.rb +1 -1
  86. data/spec/lib/models/revocable_spec.rb +3 -3
  87. data/spec/lib/oauth/authorization_code_request_spec.rb +127 -125
  88. data/spec/lib/oauth/base_request_spec.rb +160 -158
  89. data/spec/lib/oauth/base_response_spec.rb +27 -29
  90. data/spec/lib/oauth/client/credentials_spec.rb +1 -1
  91. data/spec/lib/oauth/client_credentials/creator_spec.rb +42 -5
  92. data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
  93. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  94. data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
  95. data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
  96. data/spec/lib/oauth/client_spec.rb +26 -26
  97. data/spec/lib/oauth/code_request_spec.rb +34 -34
  98. data/spec/lib/oauth/code_response_spec.rb +21 -25
  99. data/spec/lib/oauth/error_response_spec.rb +42 -44
  100. data/spec/lib/oauth/error_spec.rb +12 -14
  101. data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
  102. data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
  103. data/spec/lib/oauth/invalid_request_response_spec.rb +48 -50
  104. data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
  105. data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
  106. data/spec/lib/oauth/pre_authorization_spec.rb +159 -161
  107. data/spec/lib/oauth/refresh_token_request_spec.rb +138 -139
  108. data/spec/lib/oauth/scopes_spec.rb +104 -106
  109. data/spec/lib/oauth/token_request_spec.rb +115 -111
  110. data/spec/lib/oauth/token_response_spec.rb +71 -73
  111. data/spec/lib/oauth/token_spec.rb +121 -123
  112. data/spec/models/doorkeeper/access_grant_spec.rb +3 -5
  113. data/spec/models/doorkeeper/access_token_spec.rb +7 -7
  114. data/spec/models/doorkeeper/application_spec.rb +295 -373
  115. data/spec/requests/applications/applications_request_spec.rb +1 -1
  116. data/spec/requests/endpoints/authorization_spec.rb +5 -3
  117. data/spec/requests/flows/authorization_code_spec.rb +34 -22
  118. data/spec/requests/flows/client_credentials_spec.rb +1 -1
  119. data/spec/requests/flows/password_spec.rb +32 -12
  120. data/spec/requests/flows/refresh_token_spec.rb +19 -19
  121. data/spec/requests/flows/revoke_token_spec.rb +18 -12
  122. data/spec/spec_helper.rb +1 -4
  123. data/spec/support/shared/controllers_shared_context.rb +33 -23
  124. data/spec/validators/redirect_uri_validator_spec.rb +1 -1
  125. metadata +6 -5
  126. data/spec/support/http_method_shim.rb +0 -29
@@ -2,177 +2,176 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- module Doorkeeper::OAuth
6
- describe RefreshTokenRequest do
7
- let(:server) do
8
- double :server,
9
- access_token_expires_in: 2.minutes
10
- end
5
+ describe Doorkeeper::OAuth::RefreshTokenRequest do
6
+ let(:server) do
7
+ double :server,
8
+ access_token_expires_in: 2.minutes
9
+ end
11
10
 
12
- let(:refresh_token) do
13
- FactoryBot.create(:access_token, use_refresh_token: true)
14
- end
11
+ let(:refresh_token) do
12
+ FactoryBot.create(:access_token, use_refresh_token: true)
13
+ end
15
14
 
16
- let(:client) { refresh_token.application }
17
- let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
15
+ let(:client) { refresh_token.application }
16
+ let(:credentials) { Doorkeeper::OAuth::Client::Credentials.new(client.uid, client.secret) }
18
17
 
19
- before do
20
- allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
21
- allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(false)
22
- end
18
+ before do
19
+ allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
20
+ allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(false)
21
+ end
23
22
 
24
- subject { RefreshTokenRequest.new server, refresh_token, credentials }
23
+ subject { described_class.new server, refresh_token, credentials }
25
24
 
26
- it "issues a new token for the client" do
27
- expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
28
- # #sort_by used for MongoDB ORM extensions for valid ordering
29
- expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(120)
30
- end
25
+ it "issues a new token for the client" do
26
+ expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
27
+ # #sort_by used for MongoDB ORM extensions for valid ordering
28
+ expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(120)
29
+ end
31
30
 
32
- it "issues a new token for the client with custom expires_in" do
33
- server = double :server,
34
- access_token_expires_in: 2.minutes,
35
- custom_access_token_expires_in: lambda { |context|
36
- context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
37
- }
31
+ it "issues a new token for the client with custom expires_in" do
32
+ server = double :server,
33
+ access_token_expires_in: 2.minutes,
34
+ custom_access_token_expires_in: lambda { |context|
35
+ context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
36
+ }
38
37
 
39
- allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
40
- allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
38
+ allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
39
+ allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
41
40
 
42
- RefreshTokenRequest.new(server, refresh_token, credentials).authorize
41
+ described_class.new(server, refresh_token, credentials).authorize
43
42
 
44
- # #sort_by used for MongoDB ORM extensions for valid ordering
45
- expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
46
- end
43
+ # #sort_by used for MongoDB ORM extensions for valid ordering
44
+ expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
45
+ end
46
+
47
+ it "revokes the previous token" do
48
+ expect { subject.authorize }.to change { refresh_token.revoked? }.from(false).to(true)
49
+ end
50
+
51
+ it "calls configured request callback methods" do
52
+ expect(Doorkeeper.configuration.before_successful_strategy_response)
53
+ .to receive(:call).with(subject).once
54
+
55
+ expect(Doorkeeper.configuration.after_successful_strategy_response)
56
+ .to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
57
+
58
+ subject.authorize
59
+ end
60
+
61
+ it "requires the refresh token" do
62
+ subject.refresh_token = nil
63
+ subject.validate
64
+ expect(subject.error).to eq(:invalid_request)
65
+ expect(subject.missing_param).to eq(:refresh_token)
66
+ end
67
+
68
+ it "requires credentials to be valid if provided" do
69
+ subject.client = nil
70
+ subject.validate
71
+ expect(subject.error).to eq(:invalid_client)
72
+ end
73
+
74
+ it "requires the token's client and current client to match" do
75
+ subject.client = FactoryBot.create(:application)
76
+ subject.validate
77
+ expect(subject.error).to eq(:invalid_grant)
78
+ end
79
+
80
+ it "rejects revoked tokens" do
81
+ refresh_token.revoke
82
+ subject.validate
83
+ expect(subject.error).to eq(:invalid_grant)
84
+ end
85
+
86
+ it "accepts expired tokens" do
87
+ refresh_token.expires_in = -1
88
+ refresh_token.save
89
+ subject.validate
90
+ expect(subject).to be_valid
91
+ end
47
92
 
48
- it "revokes the previous token" do
49
- expect { subject.authorize }.to change { refresh_token.revoked? }.from(false).to(true)
93
+ context "refresh tokens expire on access token use" do
94
+ let(:server) do
95
+ double :server,
96
+ access_token_expires_in: 2.minutes,
97
+ custom_access_token_expires_in: lambda { |context|
98
+ context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
99
+ }
50
100
  end
51
101
 
52
- it "calls configured request callback methods" do
53
- expect(Doorkeeper.configuration.before_successful_strategy_response)
54
- .to receive(:call).with(subject).once
102
+ before do
103
+ allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(true)
104
+ end
55
105
 
56
- expect(Doorkeeper.configuration.after_successful_strategy_response)
57
- .to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
106
+ it "issues a new token for the client" do
107
+ expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
108
+ end
58
109
 
110
+ it "does not revoke the previous token" do
59
111
  subject.authorize
112
+ expect(refresh_token).not_to be_revoked
60
113
  end
61
114
 
62
- it "requires the refresh token" do
63
- subject.refresh_token = nil
64
- subject.validate
65
- expect(subject.error).to eq(:invalid_request)
66
- expect(subject.missing_param).to eq(:refresh_token)
115
+ it "sets the previous refresh token in the new access token" do
116
+ subject.authorize
117
+ expect(
118
+ # #sort_by used for MongoDB ORM extensions for valid ordering
119
+ client.access_tokens.max_by(&:created_at).previous_refresh_token,
120
+ ).to eq(refresh_token.refresh_token)
67
121
  end
122
+ end
68
123
 
69
- it "requires credentials to be valid if provided" do
70
- subject.client = nil
71
- subject.validate
72
- expect(subject.error).to eq(:invalid_client)
73
- end
124
+ context "clientless access tokens" do
125
+ let!(:refresh_token) { FactoryBot.create(:clientless_access_token, use_refresh_token: true) }
74
126
 
75
- it "requires the token's client and current client to match" do
76
- subject.client = FactoryBot.create(:application)
77
- subject.validate
78
- expect(subject.error).to eq(:invalid_grant)
127
+ subject { described_class.new server, refresh_token, nil }
128
+
129
+ it "issues a new token without a client" do
130
+ expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
79
131
  end
132
+ end
80
133
 
81
- it "rejects revoked tokens" do
82
- refresh_token.revoke
83
- subject.validate
84
- expect(subject.error).to eq(:invalid_grant)
134
+ context "with scopes" do
135
+ let(:refresh_token) do
136
+ FactoryBot.create :access_token,
137
+ use_refresh_token: true,
138
+ scopes: "public write"
85
139
  end
140
+ let(:parameters) { {} }
86
141
 
87
- it "accepts expired tokens" do
88
- refresh_token.expires_in = -1
89
- refresh_token.save
90
- subject.validate
91
- expect(subject).to be_valid
142
+ subject { described_class.new server, refresh_token, credentials, parameters }
143
+
144
+ it "transfers scopes from the old token to the new token" do
145
+ subject.authorize
146
+ expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
92
147
  end
93
148
 
94
- context "refresh tokens expire on access token use" do
95
- let(:server) do
96
- double :server,
97
- access_token_expires_in: 2.minutes,
98
- custom_access_token_expires_in: lambda { |context|
99
- context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
100
- }
101
- end
102
-
103
- before do
104
- allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(true)
105
- end
106
-
107
- it "issues a new token for the client" do
108
- expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
109
- end
110
-
111
- it "does not revoke the previous token" do
112
- subject.authorize
113
- expect(refresh_token).not_to be_revoked
114
- end
115
-
116
- it "sets the previous refresh token in the new access token" do
117
- subject.authorize
118
- expect(
119
- # #sort_by used for MongoDB ORM extensions for valid ordering
120
- client.access_tokens.max_by(&:created_at).previous_refresh_token
121
- ).to eq(refresh_token.refresh_token)
122
- end
149
+ it "reduces scopes to the provided scopes" do
150
+ parameters[:scopes] = "public"
151
+ subject.authorize
152
+ expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
123
153
  end
124
154
 
125
- context "clientless access tokens" do
126
- let!(:refresh_token) { FactoryBot.create(:clientless_access_token, use_refresh_token: true) }
155
+ it "validates that scopes are included in the original access token" do
156
+ parameters[:scopes] = "public update"
127
157
 
128
- subject { RefreshTokenRequest.new server, refresh_token, nil }
158
+ subject.validate
159
+ expect(subject.error).to eq(:invalid_scope)
160
+ end
129
161
 
130
- it "issues a new token without a client" do
131
- expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
132
- end
162
+ it "uses params[:scope] in favor of scopes if present (valid)" do
163
+ parameters[:scopes] = "public update"
164
+ parameters[:scope] = "public"
165
+ subject.authorize
166
+ expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
133
167
  end
134
168
 
135
- context "with scopes" do
136
- let(:refresh_token) do
137
- FactoryBot.create :access_token,
138
- use_refresh_token: true,
139
- scopes: "public write"
140
- end
141
- let(:parameters) { {} }
142
- subject { RefreshTokenRequest.new server, refresh_token, credentials, parameters }
143
-
144
- it "transfers scopes from the old token to the new token" do
145
- subject.authorize
146
- expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
147
- end
148
-
149
- it "reduces scopes to the provided scopes" do
150
- parameters[:scopes] = "public"
151
- subject.authorize
152
- expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
153
- end
154
-
155
- it "validates that scopes are included in the original access token" do
156
- parameters[:scopes] = "public update"
157
-
158
- subject.validate
159
- expect(subject.error).to eq(:invalid_scope)
160
- end
161
-
162
- it "uses params[:scope] in favor of scopes if present (valid)" do
163
- parameters[:scopes] = "public update"
164
- parameters[:scope] = "public"
165
- subject.authorize
166
- expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
167
- end
168
-
169
- it "uses params[:scope] in favor of scopes if present (invalid)" do
170
- parameters[:scopes] = "public"
171
- parameters[:scope] = "public update"
172
-
173
- subject.validate
174
- expect(subject.error).to eq(:invalid_scope)
175
- end
169
+ it "uses params[:scope] in favor of scopes if present (invalid)" do
170
+ parameters[:scopes] = "public"
171
+ parameters[:scope] = "public update"
172
+
173
+ subject.validate
174
+ expect(subject.error).to eq(:invalid_scope)
176
175
  end
177
176
  end
178
177
  end
@@ -2,147 +2,145 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- module Doorkeeper::OAuth
6
- describe Scopes do
7
- describe "#add" do
8
- it "allows you to add scopes with symbols" do
9
- subject.add :public
10
- expect(subject.all).to eq(["public"])
11
- end
5
+ describe Doorkeeper::OAuth::Scopes do
6
+ describe "#add" do
7
+ it "allows you to add scopes with symbols" do
8
+ subject.add :public
9
+ expect(subject.all).to eq(["public"])
10
+ end
12
11
 
13
- it "allows you to add scopes with strings" do
14
- subject.add "public"
15
- expect(subject.all).to eq(["public"])
16
- end
12
+ it "allows you to add scopes with strings" do
13
+ subject.add "public"
14
+ expect(subject.all).to eq(["public"])
15
+ end
17
16
 
18
- it "do not add already included scopes" do
19
- subject.add :public
20
- subject.add :public
21
- expect(subject.all).to eq(["public"])
22
- end
17
+ it "do not add already included scopes" do
18
+ subject.add :public
19
+ subject.add :public
20
+ expect(subject.all).to eq(["public"])
23
21
  end
22
+ end
24
23
 
25
- describe "#exists" do
26
- before do
27
- subject.add :public
28
- end
24
+ describe "#exists" do
25
+ before do
26
+ subject.add :public
27
+ end
29
28
 
30
- it "returns true if scope with given name is present" do
31
- expect(subject.exists?("public")).to be_truthy
32
- end
29
+ it "returns true if scope with given name is present" do
30
+ expect(subject.exists?("public")).to be_truthy
31
+ end
33
32
 
34
- it "returns false if scope with given name does not exist" do
35
- expect(subject.exists?("other")).to be_falsey
36
- end
33
+ it "returns false if scope with given name does not exist" do
34
+ expect(subject.exists?("other")).to be_falsey
35
+ end
37
36
 
38
- it "handles symbols" do
39
- expect(subject.exists?(:public)).to be_truthy
40
- expect(subject.exists?(:other)).to be_falsey
41
- end
37
+ it "handles symbols" do
38
+ expect(subject.exists?(:public)).to be_truthy
39
+ expect(subject.exists?(:other)).to be_falsey
42
40
  end
41
+ end
43
42
 
44
- describe ".from_string" do
45
- let(:string) { "public write" }
43
+ describe ".from_string" do
44
+ let(:string) { "public write" }
46
45
 
47
- subject { Scopes.from_string(string) }
46
+ subject { described_class.from_string(string) }
48
47
 
49
- it { expect(subject).to be_a(Scopes) }
48
+ it { expect(subject).to be_a(described_class) }
50
49
 
51
- describe "#all" do
52
- it "should be an array of the expected scopes" do
53
- scopes_array = subject.all
54
- expect(scopes_array.size).to eq(2)
55
- expect(scopes_array).to include("public")
56
- expect(scopes_array).to include("write")
57
- end
50
+ describe "#all" do
51
+ it "should be an array of the expected scopes" do
52
+ scopes_array = subject.all
53
+ expect(scopes_array.size).to eq(2)
54
+ expect(scopes_array).to include("public")
55
+ expect(scopes_array).to include("write")
58
56
  end
59
57
  end
58
+ end
60
59
 
61
- describe "#+" do
62
- it "can add to another scope object" do
63
- scopes = Scopes.from_string("public") + Scopes.from_string("admin")
64
- expect(scopes.all).to eq(%w[public admin])
65
- end
60
+ describe "#+" do
61
+ it "can add to another scope object" do
62
+ scopes = described_class.from_string("public") + described_class.from_string("admin")
63
+ expect(scopes.all).to eq(%w[public admin])
64
+ end
66
65
 
67
- it "does not change the existing object" do
68
- origin = Scopes.from_string("public")
69
- expect(origin.to_s).to eq("public")
70
- end
66
+ it "does not change the existing object" do
67
+ origin = described_class.from_string("public")
68
+ expect(origin.to_s).to eq("public")
69
+ end
71
70
 
72
- it "can add an array to a scope object" do
73
- scopes = Scopes.from_string("public") + ["admin"]
74
- expect(scopes.all).to eq(%w[public admin])
75
- end
71
+ it "can add an array to a scope object" do
72
+ scopes = described_class.from_string("public") + ["admin"]
73
+ expect(scopes.all).to eq(%w[public admin])
74
+ end
76
75
 
77
- it "raises an error if cannot handle addition" do
78
- expect do
79
- Scopes.from_string("public") + "admin"
80
- end.to raise_error(NoMethodError)
81
- end
76
+ it "raises an error if cannot handle addition" do
77
+ expect do
78
+ described_class.from_string("public") + "admin"
79
+ end.to raise_error(NoMethodError)
82
80
  end
81
+ end
83
82
 
84
- describe "#&" do
85
- it "can get intersection with another scope object" do
86
- scopes = Scopes.from_string("public admin") & Scopes.from_string("write admin")
87
- expect(scopes.all).to eq(%w[admin])
88
- end
83
+ describe "#&" do
84
+ it "can get intersection with another scope object" do
85
+ scopes = described_class.from_string("public admin") & described_class.from_string("write admin")
86
+ expect(scopes.all).to eq(%w[admin])
87
+ end
89
88
 
90
- it "does not change the existing object" do
91
- origin = Scopes.from_string("public admin")
92
- origin & Scopes.from_string("write admin")
93
- expect(origin.to_s).to eq("public admin")
94
- end
89
+ it "does not change the existing object" do
90
+ origin = described_class.from_string("public admin")
91
+ origin & described_class.from_string("write admin")
92
+ expect(origin.to_s).to eq("public admin")
93
+ end
95
94
 
96
- it "can get intersection with an array" do
97
- scopes = Scopes.from_string("public admin") & %w[write admin]
98
- expect(scopes.all).to eq(%w[admin])
99
- end
95
+ it "can get intersection with an array" do
96
+ scopes = described_class.from_string("public admin") & %w[write admin]
97
+ expect(scopes.all).to eq(%w[admin])
100
98
  end
99
+ end
101
100
 
102
- describe "#==" do
103
- it "is equal to another set of scopes" do
104
- expect(Scopes.from_string("public")).to eq(Scopes.from_string("public"))
105
- end
101
+ describe "#==" do
102
+ it "is equal to another set of scopes" do
103
+ expect(described_class.from_string("public")).to eq(described_class.from_string("public"))
104
+ end
106
105
 
107
- it "is equal to another set of scopes with no particular order" do
108
- expect(Scopes.from_string("public write")).to eq(Scopes.from_string("write public"))
109
- end
106
+ it "is equal to another set of scopes with no particular order" do
107
+ expect(described_class.from_string("public write")).to eq(described_class.from_string("write public"))
108
+ end
110
109
 
111
- it "differs from another set of scopes when scopes are not the same" do
112
- expect(Scopes.from_string("public write")).not_to eq(Scopes.from_string("write"))
113
- end
110
+ it "differs from another set of scopes when scopes are not the same" do
111
+ expect(described_class.from_string("public write")).not_to eq(described_class.from_string("write"))
112
+ end
114
113
 
115
- it "does not raise an error when compared to a non-enumerable object" do
116
- expect { Scopes.from_string("public") == false }.not_to raise_error
117
- end
114
+ it "does not raise an error when compared to a non-enumerable object" do
115
+ expect { described_class.from_string("public") == false }.not_to raise_error
118
116
  end
117
+ end
119
118
 
120
- describe "#has_scopes?" do
121
- subject { Scopes.from_string("public admin") }
119
+ describe "#has_scopes?" do
120
+ subject { described_class.from_string("public admin") }
122
121
 
123
- it "returns true when at least one scope is included" do
124
- expect(subject.has_scopes?(Scopes.from_string("public"))).to be_truthy
125
- end
122
+ it "returns true when at least one scope is included" do
123
+ expect(subject.has_scopes?(described_class.from_string("public"))).to be_truthy
124
+ end
126
125
 
127
- it "returns true when all scopes are included" do
128
- expect(subject.has_scopes?(Scopes.from_string("public admin"))).to be_truthy
129
- end
126
+ it "returns true when all scopes are included" do
127
+ expect(subject.has_scopes?(described_class.from_string("public admin"))).to be_truthy
128
+ end
130
129
 
131
- it "is true if all scopes are included in any order" do
132
- expect(subject.has_scopes?(Scopes.from_string("admin public"))).to be_truthy
133
- end
130
+ it "is true if all scopes are included in any order" do
131
+ expect(subject.has_scopes?(described_class.from_string("admin public"))).to be_truthy
132
+ end
134
133
 
135
- it "is false if no scopes are included" do
136
- expect(subject.has_scopes?(Scopes.from_string("notexistent"))).to be_falsey
137
- end
134
+ it "is false if no scopes are included" do
135
+ expect(subject.has_scopes?(described_class.from_string("notexistent"))).to be_falsey
136
+ end
138
137
 
139
- it "returns false when any scope is not included" do
140
- expect(subject.has_scopes?(Scopes.from_string("public nope"))).to be_falsey
141
- end
138
+ it "returns false when any scope is not included" do
139
+ expect(subject.has_scopes?(described_class.from_string("public nope"))).to be_falsey
140
+ end
142
141
 
143
- it "is false if no scopes are included even for existing ones" do
144
- expect(subject.has_scopes?(Scopes.from_string("public admin notexistent"))).to be_falsey
145
- end
142
+ it "is false if no scopes are included even for existing ones" do
143
+ expect(subject.has_scopes?(described_class.from_string("public admin notexistent"))).to be_falsey
146
144
  end
147
145
  end
148
146
  end