gds-sso 15.0.0 → 15.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +11 -6
- data/app/controllers/api/user_controller.rb +30 -28
- data/app/controllers/authentications_controller.rb +3 -5
- data/config/routes.rb +6 -5
- data/lib/gds-sso.rb +24 -23
- data/lib/gds-sso/api_access.rb +1 -1
- data/lib/gds-sso/bearer_token.rb +24 -24
- data/lib/gds-sso/config.rb +9 -5
- data/lib/gds-sso/controller_methods.rb +5 -6
- data/lib/gds-sso/failure_app.rb +7 -7
- data/lib/gds-sso/lint/user_spec.rb +24 -25
- data/lib/gds-sso/lint/user_test.rb +28 -28
- data/lib/gds-sso/user.rb +12 -12
- data/lib/gds-sso/version.rb +1 -1
- data/lib/gds-sso/warden_config.rb +21 -31
- data/spec/controller/api_user_controller_spec.rb +40 -37
- data/spec/controller/controller_methods_spec.rb +28 -28
- data/spec/internal/app/controllers/application_controller.rb +1 -1
- data/spec/internal/app/controllers/example_controller.rb +1 -2
- data/spec/internal/config/initializers/gds-sso.rb +2 -2
- data/spec/internal/config/routes.rb +2 -2
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +5 -5
- data/spec/internal/log/test.log +1079 -1079
- data/spec/requests/end_to_end_spec.rb +44 -45
- data/spec/spec_helper.rb +12 -13
- data/spec/support/signon_integration_helpers.rb +9 -7
- data/spec/support/timecop.rb +1 -1
- data/spec/unit/api_access_spec.rb +7 -7
- data/spec/unit/bearer_token_spec.rb +14 -15
- data/spec/unit/config_spec.rb +5 -5
- data/spec/unit/mock_bearer_token_spec.rb +4 -4
- data/spec/unit/session_serialisation_spec.rb +5 -5
- data/spec/unit/user_spec.rb +22 -23
- metadata +71 -57
@@ -17,58 +17,58 @@ module GDS
|
|
17
17
|
#
|
18
18
|
class UserTest < ActiveSupport::TestCase
|
19
19
|
def user_class
|
20
|
-
raise
|
20
|
+
raise "Reopen `GDS::SSO::Lint::UserTest` and add `#user_class` to return the class including `GDS::SSO::User`"
|
21
21
|
end
|
22
22
|
|
23
23
|
setup do
|
24
|
-
@lint_user = user_class.new(uid:
|
24
|
+
@lint_user = user_class.new(uid: "12345")
|
25
25
|
end
|
26
26
|
|
27
|
-
test
|
28
|
-
result = user_class.where(uid:
|
27
|
+
test "implement #where" do
|
28
|
+
result = user_class.where(uid: "123")
|
29
29
|
assert result.respond_to?(:first)
|
30
30
|
end
|
31
31
|
|
32
|
-
test
|
32
|
+
test "implement #update_attribute" do
|
33
33
|
@lint_user.update_attribute(:remotely_signed_out, true)
|
34
34
|
assert @lint_user.remotely_signed_out?
|
35
35
|
end
|
36
36
|
|
37
|
-
test
|
38
|
-
@lint_user.update!(email:
|
39
|
-
assert_equal @lint_user.email,
|
37
|
+
test "implement #update!" do
|
38
|
+
@lint_user.update!(email: "test@example.com")
|
39
|
+
assert_equal @lint_user.email, "test@example.com"
|
40
40
|
end
|
41
41
|
|
42
|
-
test
|
42
|
+
test "implement #create!" do
|
43
43
|
assert user_class.respond_to?(:create!)
|
44
44
|
end
|
45
45
|
|
46
|
-
test
|
46
|
+
test "verify the User class and GDS::SSO::User work together" do
|
47
47
|
auth_hash = {
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
"uid" => "12345",
|
49
|
+
"info" => {
|
50
|
+
"name" => "Joe Smith",
|
51
|
+
"email" => "joe.smith@example.com",
|
52
|
+
},
|
53
|
+
"extra" => {
|
54
|
+
"user" => {
|
55
|
+
"disabled" => false,
|
56
|
+
"permissions" => %w[signin],
|
57
|
+
"organisation_slug" => "cabinet-office",
|
58
|
+
"organisation_content_id" => "91e57ad9-29a3-4f94-9ab4-5e9ae6d13588",
|
59
|
+
},
|
52
60
|
},
|
53
|
-
'extra' => {
|
54
|
-
'user' => {
|
55
|
-
'disabled' => false,
|
56
|
-
'permissions' => ['signin'],
|
57
|
-
'organisation_slug' => 'cabinet-office',
|
58
|
-
'organisation_content_id' => '91e57ad9-29a3-4f94-9ab4-5e9ae6d13588',
|
59
|
-
}
|
60
|
-
}
|
61
61
|
}
|
62
62
|
|
63
63
|
user = user_class.find_for_gds_oauth(auth_hash)
|
64
64
|
assert_equal user_class, user.class
|
65
|
-
assert_equal
|
66
|
-
assert_equal
|
67
|
-
assert_equal
|
65
|
+
assert_equal "12345", user.uid
|
66
|
+
assert_equal "Joe Smith", user.name
|
67
|
+
assert_equal "joe.smith@example.com", user.email
|
68
68
|
assert_equal false, user.disabled
|
69
|
-
assert_equal [
|
70
|
-
assert_equal
|
71
|
-
assert_equal
|
69
|
+
assert_equal %w[signin], user.permissions
|
70
|
+
assert_equal "cabinet-office", user.organisation_slug
|
71
|
+
assert_equal "91e57ad9-29a3-4f94-9ab4-5e9ae6d13588", user.organisation_content_id
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
data/lib/gds-sso/user.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module GDS
|
4
4
|
module SSO
|
@@ -21,29 +21,29 @@ module GDS
|
|
21
21
|
|
22
22
|
def self.user_params_from_auth_hash(auth_hash)
|
23
23
|
{
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
"uid" => auth_hash["uid"],
|
25
|
+
"email" => auth_hash["info"]["email"],
|
26
|
+
"name" => auth_hash["info"]["name"],
|
27
|
+
"permissions" => auth_hash["extra"]["user"]["permissions"],
|
28
|
+
"organisation_slug" => auth_hash["extra"]["user"]["organisation_slug"],
|
29
|
+
"organisation_content_id" => auth_hash["extra"]["user"]["organisation_content_id"],
|
30
|
+
"disabled" => auth_hash["extra"]["user"]["disabled"],
|
31
31
|
}
|
32
32
|
end
|
33
33
|
|
34
34
|
def clear_remotely_signed_out!
|
35
|
-
|
35
|
+
update_attribute(:remotely_signed_out, false)
|
36
36
|
end
|
37
37
|
|
38
38
|
def set_remotely_signed_out!
|
39
|
-
|
39
|
+
update_attribute(:remotely_signed_out, true)
|
40
40
|
end
|
41
41
|
|
42
42
|
module ClassMethods
|
43
43
|
def find_for_gds_oauth(auth_hash)
|
44
44
|
user_params = GDS::SSO::User.user_params_from_auth_hash(auth_hash.to_hash)
|
45
|
-
user =
|
46
|
-
|
45
|
+
user = where(uid: user_params["uid"]).first ||
|
46
|
+
where(email: user_params["email"]).first
|
47
47
|
|
48
48
|
if user
|
49
49
|
user.update!(user_params)
|
data/lib/gds-sso/version.rb
CHANGED
@@ -1,63 +1,55 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "warden"
|
2
|
+
require "warden-oauth2"
|
3
|
+
require "gds-sso/bearer_token"
|
4
4
|
|
5
5
|
def logger
|
6
|
-
|
7
|
-
Rails.logger
|
8
|
-
else
|
9
|
-
env['rack.logger']
|
10
|
-
end
|
6
|
+
Rails.logger || env["rack.logger"]
|
11
7
|
end
|
12
8
|
|
13
|
-
Warden::Manager.after_authentication do |user,
|
9
|
+
Warden::Manager.after_authentication do |user, _auth, _opts|
|
14
10
|
# We've successfully signed in.
|
15
11
|
# If they were remotely signed out, clear the flag as they're no longer suspended
|
16
12
|
user.clear_remotely_signed_out!
|
17
13
|
end
|
18
14
|
|
19
15
|
Warden::Manager.serialize_into_session do |user|
|
20
|
-
if user.respond_to?(:uid)
|
16
|
+
if user.respond_to?(:uid) && user.uid
|
21
17
|
[user.uid, Time.now.utc.iso8601]
|
22
|
-
else
|
23
|
-
nil
|
24
18
|
end
|
25
19
|
end
|
26
20
|
|
27
21
|
Warden::Manager.serialize_from_session do |(uid, auth_timestamp)|
|
28
22
|
# This will reject old sessions that don't have a previous login timestamp
|
29
23
|
if auth_timestamp.is_a?(String)
|
30
|
-
|
31
|
-
Time.parse(auth_timestamp)
|
24
|
+
begin
|
25
|
+
auth_timestamp = Time.parse(auth_timestamp)
|
32
26
|
rescue ArgumentError
|
33
|
-
nil
|
27
|
+
auth_timestamp = nil
|
34
28
|
end
|
35
29
|
end
|
36
30
|
|
37
|
-
if auth_timestamp
|
38
|
-
GDS::SSO::Config.user_klass.where(:
|
39
|
-
else
|
40
|
-
nil
|
31
|
+
if auth_timestamp && ((auth_timestamp + GDS::SSO::Config.auth_valid_for) > Time.now.utc)
|
32
|
+
GDS::SSO::Config.user_klass.where(uid: uid, remotely_signed_out: false).first
|
41
33
|
end
|
42
34
|
end
|
43
35
|
|
44
36
|
Warden::Strategies.add(:gds_sso) do
|
45
37
|
def valid?
|
46
|
-
|
38
|
+
!::GDS::SSO::ApiAccess.api_call?(env)
|
47
39
|
end
|
48
40
|
|
49
41
|
def authenticate!
|
50
42
|
logger.debug("Authenticating with gds_sso strategy")
|
51
43
|
|
52
|
-
if request.env[
|
44
|
+
if request.env["omniauth.auth"].nil?
|
53
45
|
fail!("No credentials, bub")
|
54
46
|
else
|
55
|
-
user = prep_user(request.env[
|
47
|
+
user = prep_user(request.env["omniauth.auth"])
|
56
48
|
success!(user)
|
57
49
|
end
|
58
50
|
end
|
59
51
|
|
60
|
-
|
52
|
+
private
|
61
53
|
|
62
54
|
def prep_user(auth_hash)
|
63
55
|
user = GDS::SSO::Config.user_klass.find_for_gds_oauth(auth_hash)
|
@@ -73,27 +65,25 @@ Warden::Strategies.add(:gds_bearer_token, Warden::OAuth2::Strategies::Bearer)
|
|
73
65
|
|
74
66
|
Warden::Strategies.add(:mock_gds_sso) do
|
75
67
|
def valid?
|
76
|
-
|
68
|
+
!::GDS::SSO::ApiAccess.api_call?(env)
|
77
69
|
end
|
78
70
|
|
79
71
|
def authenticate!
|
80
72
|
logger.warn("Authenticating with mock_gds_sso strategy")
|
81
73
|
|
82
74
|
test_user = GDS::SSO.test_user
|
83
|
-
test_user ||= ENV[
|
75
|
+
test_user ||= ENV["GDS_SSO_MOCK_INVALID"].present? ? nil : GDS::SSO::Config.user_klass.first
|
84
76
|
if test_user
|
85
77
|
# Brute force ensure test user has correct perms to signin
|
86
|
-
|
78
|
+
unless test_user.has_permission?("signin")
|
87
79
|
permissions = test_user.permissions || []
|
88
80
|
test_user.update_attribute(:permissions, permissions << "signin")
|
89
81
|
end
|
90
82
|
success!(test_user)
|
83
|
+
elsif Rails.env.test? && ENV["GDS_SSO_MOCK_INVALID"].present?
|
84
|
+
fail!(:invalid)
|
91
85
|
else
|
92
|
-
|
93
|
-
fail!(:invalid)
|
94
|
-
else
|
95
|
-
raise "GDS-SSO running in mock mode and no test user found. Normally we'd load the first user in the database. Create a user in the database."
|
96
|
-
end
|
86
|
+
raise "GDS-SSO running in mock mode and no test user found. Normally we'd load the first user in the database. Create a user in the database."
|
97
87
|
end
|
98
88
|
end
|
99
89
|
end
|
@@ -10,24 +10,25 @@ def user_update_json
|
|
10
10
|
"organisation_slug" => "justice-league",
|
11
11
|
"organisation_content_id" => "aae1319e-5788-4677-998c-f1a53af528d0",
|
12
12
|
"disabled" => false,
|
13
|
-
}
|
13
|
+
},
|
14
14
|
}.to_json
|
15
15
|
end
|
16
16
|
|
17
17
|
describe Api::UserController, type: :controller do
|
18
|
-
|
19
18
|
before :each do
|
20
19
|
user_to_update_attrs = [{
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
uid: "a1s2d3#{rand(10_000)}",
|
21
|
+
email: "old@domain.com",
|
22
|
+
name: "Moshua Jarshall",
|
23
|
+
permissions: %w[signin],
|
24
|
+
}]
|
25
|
+
|
26
|
+
signon_sso_push_user_attrs = [{
|
27
|
+
uid: "a1s2d3#{rand(10_000)}",
|
28
|
+
email: "ssopushuser@legit.com",
|
29
|
+
name: "SSO Push user",
|
30
|
+
permissions: %w[signin user_update_permission],
|
31
|
+
}]
|
31
32
|
|
32
33
|
@user_to_update = User.create!(*user_to_update_attrs)
|
33
34
|
@signon_sso_push_user = User.create!(*signon_sso_push_user_attrs)
|
@@ -36,13 +37,14 @@ describe Api::UserController, type: :controller do
|
|
36
37
|
describe "PUT update" do
|
37
38
|
it "should deny access to anybody but the API user (or a user with 'user_update_permission')" do
|
38
39
|
malicious_user = User.new({
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
uid: "2",
|
41
|
+
name: "User",
|
42
|
+
permissions: %w[signin],
|
43
|
+
})
|
42
44
|
|
43
|
-
request.env[
|
45
|
+
request.env["warden"] = double("stub warden", authenticate!: true, authenticated?: true, user: malicious_user)
|
44
46
|
|
45
|
-
request.env[
|
47
|
+
request.env["RAW_POST_DATA"] = user_update_json
|
46
48
|
put :update, body: user_update_json, params: { uid: @user_to_update.uid }
|
47
49
|
|
48
50
|
expect(response.status).to eq(403)
|
@@ -50,12 +52,12 @@ describe Api::UserController, type: :controller do
|
|
50
52
|
|
51
53
|
it "should create/update the user record in the same way as the OAuth callback" do
|
52
54
|
# Test that it authenticates
|
53
|
-
request.env[
|
54
|
-
expect(request.env[
|
55
|
-
expect(request.env[
|
56
|
-
expect(request.env[
|
55
|
+
request.env["warden"] = double("mock warden")
|
56
|
+
expect(request.env["warden"]).to receive(:authenticate!).at_least(:once).and_return(true)
|
57
|
+
expect(request.env["warden"]).to receive(:authenticated?).at_least(:once).and_return(true)
|
58
|
+
expect(request.env["warden"]).to receive(:user).at_least(:once).and_return(@signon_sso_push_user)
|
57
59
|
|
58
|
-
request.env[
|
60
|
+
request.env["RAW_POST_DATA"] = user_update_json
|
59
61
|
put :update, body: user_update_json, params: { uid: @user_to_update.uid }
|
60
62
|
|
61
63
|
@user_to_update.reload
|
@@ -64,18 +66,19 @@ describe Api::UserController, type: :controller do
|
|
64
66
|
expect(@user_to_update.permissions).to eq(["signin", "new permission"])
|
65
67
|
expect(@user_to_update.organisation_slug).to eq("justice-league")
|
66
68
|
expect(@user_to_update.organisation_content_id).to eq("aae1319e-5788-4677-998c-f1a53af528d0")
|
67
|
-
expect(response.content_type).to eq(
|
69
|
+
expect(response.content_type).to eq("text/plain")
|
68
70
|
end
|
69
71
|
end
|
70
72
|
|
71
73
|
describe "POST reauth" do
|
72
74
|
it "should deny access to anybody but the API user (or a user with 'user_update_permission')" do
|
73
75
|
malicious_user = User.new({
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
uid: "2",
|
77
|
+
name: "User",
|
78
|
+
permissions: %w[signin],
|
79
|
+
})
|
77
80
|
|
78
|
-
request.env[
|
81
|
+
request.env["warden"] = double("stub warden", authenticate!: true, authenticated?: true, user: malicious_user)
|
79
82
|
|
80
83
|
post :reauth, params: { uid: @user_to_update.uid }
|
81
84
|
|
@@ -83,29 +86,29 @@ describe Api::UserController, type: :controller do
|
|
83
86
|
end
|
84
87
|
|
85
88
|
it "should return success if user record doesn't exist" do
|
86
|
-
request.env[
|
87
|
-
expect(request.env[
|
88
|
-
expect(request.env[
|
89
|
-
expect(request.env[
|
89
|
+
request.env["warden"] = double("mock warden")
|
90
|
+
expect(request.env["warden"]).to receive(:authenticate!).at_least(:once).and_return(true)
|
91
|
+
expect(request.env["warden"]).to receive(:authenticated?).at_least(:once).and_return(true)
|
92
|
+
expect(request.env["warden"]).to receive(:user).at_least(:once).and_return(@signon_sso_push_user)
|
90
93
|
|
91
94
|
post :reauth, params: { uid: "nonexistent-user" }
|
92
95
|
|
93
96
|
expect(response.status).to eq(200)
|
94
|
-
expect(response.content_type).to eq(
|
97
|
+
expect(response.content_type).to eq("text/plain")
|
95
98
|
end
|
96
99
|
|
97
100
|
it "should set remotely_signed_out to true on the user" do
|
98
101
|
# Test that it authenticates
|
99
|
-
request.env[
|
100
|
-
expect(request.env[
|
101
|
-
expect(request.env[
|
102
|
-
expect(request.env[
|
102
|
+
request.env["warden"] = double("mock warden")
|
103
|
+
expect(request.env["warden"]).to receive(:authenticate!).at_least(:once).and_return(true)
|
104
|
+
expect(request.env["warden"]).to receive(:authenticated?).at_least(:once).and_return(true)
|
105
|
+
expect(request.env["warden"]).to receive(:user).at_least(:once).and_return(@signon_sso_push_user)
|
103
106
|
|
104
107
|
post :reauth, params: { uid: @user_to_update.uid }
|
105
108
|
|
106
109
|
@user_to_update.reload
|
107
110
|
expect(@user_to_update).to be_remotely_signed_out
|
108
|
-
expect(response.content_type).to eq(
|
111
|
+
expect(response.content_type).to eq("text/plain")
|
109
112
|
end
|
110
113
|
end
|
111
114
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
|
-
RSpec.describe GDS::SSO::ControllerMethods,
|
3
|
+
RSpec.describe GDS::SSO::ControllerMethods, "#authorise_user!" do
|
4
4
|
class ControllerSpy < ApplicationController
|
5
5
|
include GDS::SSO::ControllerMethods
|
6
6
|
|
@@ -18,54 +18,54 @@ RSpec.describe GDS::SSO::ControllerMethods, '#authorise_user!' do
|
|
18
18
|
let(:current_user) { double }
|
19
19
|
let(:expected_error) { GDS::SSO::ControllerMethods::PermissionDeniedException }
|
20
20
|
|
21
|
-
context
|
22
|
-
it
|
23
|
-
allow(current_user).to receive(:has_permission?).with(
|
21
|
+
context "with a single string permission argument" do
|
22
|
+
it "permits users with the required permission" do
|
23
|
+
allow(current_user).to receive(:has_permission?).with("good").and_return(true)
|
24
24
|
|
25
|
-
expect { ControllerSpy.new(current_user).authorise_user!(
|
25
|
+
expect { ControllerSpy.new(current_user).authorise_user!("good") }.not_to raise_error
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
29
|
-
allow(current_user).to receive(:has_permission?).with(
|
28
|
+
it "does not permit the users without the required permission" do
|
29
|
+
allow(current_user).to receive(:has_permission?).with("good").and_return(false)
|
30
30
|
|
31
|
-
expect { ControllerSpy.new(current_user).authorise_user!(
|
31
|
+
expect { ControllerSpy.new(current_user).authorise_user!("good") }.to raise_error(expected_error)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
context
|
36
|
-
it
|
37
|
-
allow(current_user).to receive(:has_permission?).with(
|
38
|
-
allow(current_user).to receive(:has_permission?).with(
|
35
|
+
context "with the `all_of` option" do
|
36
|
+
it "permits users with all of the required permissions" do
|
37
|
+
allow(current_user).to receive(:has_permission?).with("good").and_return(true)
|
38
|
+
allow(current_user).to receive(:has_permission?).with("bad").and_return(true)
|
39
39
|
|
40
|
-
expect { ControllerSpy.new(current_user).authorise_user!(all_of: %w
|
40
|
+
expect { ControllerSpy.new(current_user).authorise_user!(all_of: %w[good bad]) }.not_to raise_error
|
41
41
|
end
|
42
42
|
|
43
|
-
it
|
44
|
-
allow(current_user).to receive(:has_permission?).with(
|
45
|
-
allow(current_user).to receive(:has_permission?).with(
|
43
|
+
it "does not permit users without all of the required permissions" do
|
44
|
+
allow(current_user).to receive(:has_permission?).with("good").and_return(false)
|
45
|
+
allow(current_user).to receive(:has_permission?).with("bad").and_return(true)
|
46
46
|
|
47
|
-
expect { ControllerSpy.new(current_user).authorise_user!(all_of: %w
|
47
|
+
expect { ControllerSpy.new(current_user).authorise_user!(all_of: %w[good bad]) }.to raise_error(expected_error)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
context
|
52
|
-
it
|
53
|
-
allow(current_user).to receive(:has_permission?).with(
|
54
|
-
allow(current_user).to receive(:has_permission?).with(
|
51
|
+
context "with the `any_of` option" do
|
52
|
+
it "permits users with any of the required permissions" do
|
53
|
+
allow(current_user).to receive(:has_permission?).with("good").and_return(true)
|
54
|
+
allow(current_user).to receive(:has_permission?).with("bad").and_return(false)
|
55
55
|
|
56
|
-
expect { ControllerSpy.new(current_user).authorise_user!(any_of: %w
|
56
|
+
expect { ControllerSpy.new(current_user).authorise_user!(any_of: %w[good bad]) }.not_to raise_error
|
57
57
|
end
|
58
58
|
|
59
|
-
it
|
59
|
+
it "does not permit users without any of the required permissions" do
|
60
60
|
allow(current_user).to receive(:has_permission?).and_return(false)
|
61
61
|
|
62
|
-
expect { ControllerSpy.new(current_user).authorise_user!(any_of: %w
|
62
|
+
expect { ControllerSpy.new(current_user).authorise_user!(any_of: %w[good bad]) }.to raise_error(expected_error)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
context
|
67
|
-
it
|
68
|
-
expect { ControllerSpy.new(current_user).authorise_user!(whoops:
|
66
|
+
context "with none of `any_of` or `all_of`" do
|
67
|
+
it "raises an `ArgumentError`" do
|
68
|
+
expect { ControllerSpy.new(current_user).authorise_user!(whoops: "bad") }.to raise_error(ArgumentError)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|