shibbolite 0.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +9 -11
- data/app/concerns/shibbolite/filters.rb +26 -8
- data/app/concerns/shibbolite/helpers.rb +6 -0
- data/app/controllers/shibbolite/shibboleth_controller.rb +11 -1
- data/lib/shibbolite/version.rb +1 -1
- data/spec/controllers/filters_test_controller_spec.rb +62 -3
- data/spec/controllers/helpers_test_controller_spec.rb +29 -12
- data/spec/dummy/app/controllers/filters_test_controller.rb +10 -0
- data/spec/dummy/app/controllers/helpers_test_controller.rb +5 -0
- data/spec/dummy/app/views/static/home.html.erb +3 -1
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +727 -0
- data/spec/dummy/log/test.log +24242 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/371bf96e99717688ed7313a0c53f4212 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/510da110ae528e2d22533be39ff696c5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6fc757c2c8329244ca95d6909865bbc2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/371bf96e99717688ed7313a0c53f4212 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6fc757c2c8329244ca95d6909865bbc2 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/tmp/restart.txt +0 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/controllers/shared_access_control_examples.rb +63 -0
- data/spec/support/controllers/shared_auth_helpers.rb +25 -0
- data/spec/support/features/session_helpers.rb +12 -0
- metadata +102 -110
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f736be4c42d9b6feef36b94647b8fbf3bf4ce8c4
|
4
|
+
data.tar.gz: bb91bf1108e56142cf9ef106139d54c8313e579a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 08bbe01087d289f772581b2ce7ad1bf243155c3d1291f931b72f47f446ebc57207bb2d6b55e95765df8d9e2f9c977fb40a9a604fb8bd1c09bd9eb9278a7df75c
|
7
|
+
data.tar.gz: 1ab7667eaee8c9e3200512dc379e9ecf221d26d5d2d5960f1a5701b236674d234202ca815cecca0aac7edabc542bea0853a513a2ae0263a4e86c1bbc9ba7582b
|
data/README.rdoc
CHANGED
@@ -48,47 +48,45 @@ Shibbolite::Filters gives you a gaggle of before filters to enable access contro
|
|
48
48
|
=== Filters
|
49
49
|
before_action :require_login
|
50
50
|
|
51
|
-
|
51
|
+
...in your ApplicationController will require that users have a valid Shibboleth session before they can launch any action
|
52
52
|
|
53
53
|
before_action { |c| c.require_group :admin }
|
54
54
|
|
55
|
-
will require that the user belong to the admin group
|
55
|
+
...will require that the user belong to the admin group
|
56
56
|
|
57
57
|
before_action { |c| c.require_group :admin, :user }
|
58
58
|
|
59
|
-
will allow anyone who has the admin or the user group
|
59
|
+
...will allow anyone who has the admin or the user group
|
60
60
|
|
61
61
|
before_action { |c| c.require_group_or_id :admin, some_user.id }
|
62
62
|
|
63
|
-
is useful for things like profile pages that are accessible to both an owner and anyone in the admin group
|
63
|
+
...is useful for things like profile pages that are accessible to both an owner and anyone in the admin group
|
64
64
|
|
65
65
|
before_action :use_attributes_if_available, only: :public
|
66
66
|
|
67
|
-
will attempt to load a Shibboleth session if one is available but do nothing otherwise. Use this if you have a public page but still want to make use of attributes for users that have logged in.
|
67
|
+
...will attempt to load a Shibboleth session if one is available but do nothing otherwise. Use this if you have a public page but still want to make use of attributes for users that have logged in.
|
68
68
|
|
69
69
|
=== Helpers
|
70
70
|
These helpers will be available to views of any controllers that include Shibbolite::Filters. See the source for a complete list.
|
71
71
|
|
72
72
|
current_user
|
73
73
|
|
74
|
-
will return the User object of the Shibboleth authenticated user or nil if no one is authenticated, or the user isn't registered in the database. NOTE: current_user can still return nil after the user authenticates if one of the above filters isn't used before the controller action.
|
74
|
+
...will return the User object of the Shibboleth authenticated user or nil if no one is authenticated, or the user isn't registered in the database. NOTE: current_user can still return nil after the user authenticates if one of the above filters isn't used before the controller action.
|
75
75
|
|
76
76
|
Since current_user relies on a database lookup, you'll have to register (ie persist) your users before they can interact with most of the features of Shibbolite. How you want to handle user registration is left up to you.
|
77
77
|
|
78
78
|
logged_in?
|
79
79
|
|
80
|
-
checks to see that a username is set in the session
|
80
|
+
...checks to see that a username is set in the session
|
81
81
|
|
82
82
|
user_in_group? (:admin)
|
83
83
|
|
84
|
-
will return true if the current user has the admin group
|
85
|
-
|
86
|
-
|
84
|
+
...will return true if the current user has the admin group
|
87
85
|
|
88
86
|
=== Actions
|
89
87
|
A couple of actions are available from Shibbolite::ShibbolethController
|
90
88
|
|
91
|
-
shibbolite.login_path #=> '
|
89
|
+
shibbolite.login_path #=> 'shibbolite/login'
|
92
90
|
|
93
91
|
will attempt to load a Shibboleth session, or redirect to the Shibbolite.session_initiator for authentication if there is none. After authentication the user is brought back to the root_path.
|
94
92
|
|
@@ -6,21 +6,21 @@ module Shibbolite
|
|
6
6
|
include Shibbolite::Helpers
|
7
7
|
|
8
8
|
def require_login
|
9
|
-
|
9
|
+
authenticate_request unless logged_in?
|
10
10
|
end
|
11
11
|
|
12
12
|
def require_registered
|
13
|
-
|
13
|
+
authenticate_request unless registered_user?
|
14
14
|
end
|
15
15
|
|
16
16
|
def require_group(*groups)
|
17
17
|
in_group = false
|
18
18
|
groups.flatten.each { |group| in_group ||= user_in_group?(group) }
|
19
|
-
|
19
|
+
authenticate_request unless in_group
|
20
20
|
end
|
21
21
|
|
22
22
|
def require_id(id)
|
23
|
-
|
23
|
+
authenticate_request unless user_has_id?(id)
|
24
24
|
end
|
25
25
|
|
26
26
|
def require_group_or_id(*groups, id)
|
@@ -29,16 +29,34 @@ module Shibbolite
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
def require_attribute(attr, value)
|
33
|
+
authenticate_request unless user_has_matching_attribute?(attr, value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def require_group_or_attribute(*groups, attr, value)
|
37
|
+
unless user_has_matching_attribute?(attr, value)
|
38
|
+
require_group(groups)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
32
42
|
def use_attributes_if_available
|
33
43
|
if request.env[Shibbolite.pid.to_s] and not logged_in?
|
34
|
-
|
44
|
+
authenticate_request
|
35
45
|
end
|
36
46
|
end
|
37
47
|
|
38
|
-
#
|
39
|
-
|
48
|
+
# redirects the user to (re)authenticate with
|
49
|
+
# the Idp or a 403 forbidden page
|
50
|
+
def authenticate_request
|
40
51
|
session[:requested_url] = request.fullpath
|
41
|
-
|
52
|
+
|
53
|
+
url = logged_in? ? shibbolite.access_denied_url : shibbolite.login_url
|
54
|
+
|
55
|
+
# redirect to the selected url
|
56
|
+
respond_to do |format|
|
57
|
+
format.html { redirect_to url }
|
58
|
+
format.js { render js: "window.location.assign('#{url}');"}
|
59
|
+
end
|
42
60
|
end
|
43
61
|
end
|
44
62
|
end
|
@@ -44,5 +44,11 @@ module Shibbolite
|
|
44
44
|
return false unless user
|
45
45
|
user.id == id
|
46
46
|
end
|
47
|
+
|
48
|
+
# this method matches against the raw environment variables
|
49
|
+
# instead of the database attributes
|
50
|
+
def user_has_matching_attribute?(attr, value)
|
51
|
+
request.env[attr.to_s] == value
|
52
|
+
end
|
47
53
|
end
|
48
54
|
end
|
@@ -9,8 +9,18 @@ module Shibbolite
|
|
9
9
|
|
10
10
|
def login
|
11
11
|
session[:requested_url] ||= main_app.root_path
|
12
|
+
|
13
|
+
# attempt to load existing sp session data
|
12
14
|
load_session
|
13
|
-
|
15
|
+
|
16
|
+
# redirect to Idp for authentication if
|
17
|
+
# sp session data is not present
|
18
|
+
url = (logged_in? ? session.delete(:requested_url) : sp_login_url)
|
19
|
+
|
20
|
+
respond_to do |format|
|
21
|
+
format.html { redirect_to url }
|
22
|
+
format.js { render js: "window.location.assign('#{url}');"}
|
23
|
+
end
|
14
24
|
end
|
15
25
|
|
16
26
|
def logout
|
data/lib/shibbolite/version.rb
CHANGED
@@ -4,6 +4,8 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe FiltersTestController do
|
6
6
|
|
7
|
+
include_context 'auth_helpers'
|
8
|
+
|
7
9
|
# presume the session has been loaded
|
8
10
|
before { allow(subject).to receive(:load_session) }
|
9
11
|
|
@@ -15,15 +17,21 @@ describe FiltersTestController do
|
|
15
17
|
get :_require_login
|
16
18
|
expect(response).to render_template(:dummy)
|
17
19
|
end
|
18
|
-
|
19
20
|
end
|
20
21
|
|
21
22
|
context 'when not logged in' do
|
23
|
+
before { allow(subject).to receive(:logged_in?).and_return(false) }
|
24
|
+
|
22
25
|
it 'redirects' do
|
23
|
-
allow(subject).to receive(:logged_in?).and_return(false)
|
24
26
|
get :_require_login
|
25
27
|
expect(response).to redirect_to('/shibbolite/login')
|
26
28
|
end
|
29
|
+
|
30
|
+
# see feature spec for complete test
|
31
|
+
it 'responds to ajax requests' do
|
32
|
+
xhr :get, :_require_login
|
33
|
+
expect(response.body).to include('window.location')
|
34
|
+
end
|
27
35
|
end
|
28
36
|
end
|
29
37
|
|
@@ -48,7 +56,7 @@ describe FiltersTestController do
|
|
48
56
|
|
49
57
|
describe '#use_attributes_if_available' do
|
50
58
|
|
51
|
-
context 'when the user authenticated but login
|
59
|
+
context 'when the user authenticated but login is not required' do
|
52
60
|
it 'redirects to login to load the session' do
|
53
61
|
allow(subject).to receive(:logged_in?).and_return(false)
|
54
62
|
request.env[Shibbolite.pid.to_s] = 'not nil'
|
@@ -65,6 +73,26 @@ describe FiltersTestController do
|
|
65
73
|
end
|
66
74
|
end
|
67
75
|
|
76
|
+
describe '#require_attribute' do
|
77
|
+
|
78
|
+
it 'executes action when user has the attribute' do
|
79
|
+
set_env_attribute(:department, '9th Circle')
|
80
|
+
get :_require_attribute, attr: :department, value: '9th Circle'
|
81
|
+
expect(response).to render_template(:dummy)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'redirects when user does not have the attribute' do
|
85
|
+
get :_require_attribute, attr: :dragon, value: 'Smaug'
|
86
|
+
expect(response).to redirect_to('/shibbolite/login')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'redirects when user has an incorrect value for the attribute' do
|
90
|
+
set_env_attribute(:department, 'Complaints')
|
91
|
+
get :_require_attribute, attr: :department, value: '9th Circle'
|
92
|
+
expect(response).to redirect_to('/shibbolite/login')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
68
96
|
context 'filters that require a user object' do
|
69
97
|
|
70
98
|
let!(:user_id) { 17 }
|
@@ -142,5 +170,36 @@ describe FiltersTestController do
|
|
142
170
|
end
|
143
171
|
end
|
144
172
|
end
|
173
|
+
|
174
|
+
describe '#require_group_or_attribute' do
|
175
|
+
context 'happy paths' do
|
176
|
+
|
177
|
+
it 'executes action when user has the attribute' do
|
178
|
+
set_env_attribute(:department, '9th Circle')
|
179
|
+
get :_require_group_or_attribute, groups: 'admin', attr: :department, value: '9th Circle'
|
180
|
+
expect(response).to render_template(:dummy)
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'allows action with matching group' do
|
184
|
+
allow(subject).to receive(:current_user).and_return(admin)
|
185
|
+
get :_require_group_or_id, groups: 'admin', attr: :department, value: '9th Circle'
|
186
|
+
expect(response).to render_template(:dummy)
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'allows action with both attribute and group matching' do
|
190
|
+
set_env_attribute(:department, '9th Circle')
|
191
|
+
allow(subject).to receive(:current_user).and_return(admin)
|
192
|
+
get :_require_group_or_id, groups: 'admin', attr: :department, value: '9th Circle'
|
193
|
+
expect(response).to render_template(:dummy)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'with no matching criteria' do
|
198
|
+
it 'redirects' do
|
199
|
+
get :_require_attribute, attr: :wizard, value: 'Gandalf'
|
200
|
+
expect(response).to redirect_to('/shibbolite/login')
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
145
204
|
end
|
146
205
|
end
|
@@ -4,6 +4,8 @@ require 'spec_helper'
|
|
4
4
|
# the Shibbolite::Helpers concern
|
5
5
|
describe HelpersTestController do
|
6
6
|
|
7
|
+
include_context 'auth_helpers'
|
8
|
+
|
7
9
|
# helper methods
|
8
10
|
#
|
9
11
|
|
@@ -38,7 +40,7 @@ describe HelpersTestController do
|
|
38
40
|
it 'is false' do
|
39
41
|
session[Shibbolite.pid] = nil
|
40
42
|
get :_logged_in?
|
41
|
-
expect(assigns(:logged_in)).to
|
43
|
+
expect(assigns(:logged_in)).to be_falsey
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
@@ -46,7 +48,7 @@ describe HelpersTestController do
|
|
46
48
|
it 'is true' do
|
47
49
|
session[Shibbolite.pid] = 'SSO authenticated'
|
48
50
|
get :_logged_in?
|
49
|
-
expect(assigns(:logged_in)).to
|
51
|
+
expect(assigns(:logged_in)).to be_truthy
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -57,7 +59,7 @@ describe HelpersTestController do
|
|
57
59
|
it 'is true' do
|
58
60
|
session[Shibbolite.pid] = nil
|
59
61
|
get :_anonymous_user?
|
60
|
-
expect(assigns(:anonymous)).to
|
62
|
+
expect(assigns(:anonymous)).to be_truthy
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
@@ -65,7 +67,7 @@ describe HelpersTestController do
|
|
65
67
|
it 'is false' do
|
66
68
|
session[Shibbolite.pid] = 'SSO authenticated'
|
67
69
|
get :_anonymous_user?
|
68
|
-
expect(assigns(:anonymous)).to
|
70
|
+
expect(assigns(:anonymous)).to be_falsey
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
@@ -77,7 +79,7 @@ describe HelpersTestController do
|
|
77
79
|
session[Shibbolite.pid] = 'SSO authenticated'
|
78
80
|
allow(subject).to receive(:current_user).and_return(nil)
|
79
81
|
get :_guest_user?
|
80
|
-
expect(assigns(:guest)).to
|
82
|
+
expect(assigns(:guest)).to be_truthy
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
@@ -86,7 +88,7 @@ describe HelpersTestController do
|
|
86
88
|
session[Shibbolite.pid] = nil
|
87
89
|
allow(subject).to receive(:current_user).and_return(nil)
|
88
90
|
get :_guest_user?
|
89
|
-
expect(assigns(:guest)).to
|
91
|
+
expect(assigns(:guest)).to be_falsey
|
90
92
|
end
|
91
93
|
end
|
92
94
|
end
|
@@ -97,7 +99,7 @@ describe HelpersTestController do
|
|
97
99
|
it 'is true' do
|
98
100
|
allow(subject).to receive(:current_user).and_return('A valid user')
|
99
101
|
get :_registered_user?
|
100
|
-
expect(assigns(:registered)).to
|
102
|
+
expect(assigns(:registered)).to be_truthy
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
@@ -105,7 +107,7 @@ describe HelpersTestController do
|
|
105
107
|
it 'is false' do
|
106
108
|
allow(subject).to receive(:current_user).and_return(nil)
|
107
109
|
get :_registered_user?
|
108
|
-
expect(assigns(:registered)).to
|
110
|
+
expect(assigns(:registered)).to be_falsey
|
109
111
|
end
|
110
112
|
end
|
111
113
|
end
|
@@ -118,12 +120,12 @@ describe HelpersTestController do
|
|
118
120
|
|
119
121
|
it 'is true when user is in group' do
|
120
122
|
get :_user_in_group?, group: 'jedi'
|
121
|
-
expect(assigns(:result)).to
|
123
|
+
expect(assigns(:result)).to be_truthy
|
122
124
|
end
|
123
125
|
|
124
126
|
it 'is false when user is not in group' do
|
125
127
|
get :_user_in_group?, group: 'sith'
|
126
|
-
expect(assigns(:result)).to
|
128
|
+
expect(assigns(:result)).to be_falsey
|
127
129
|
end
|
128
130
|
end
|
129
131
|
|
@@ -135,12 +137,27 @@ describe HelpersTestController do
|
|
135
137
|
|
136
138
|
it 'is true when user has the id' do
|
137
139
|
get :_user_has_id?, id: '17'
|
138
|
-
expect(assigns(:result)).to
|
140
|
+
expect(assigns(:result)).to be_truthy
|
139
141
|
end
|
140
142
|
|
141
143
|
it 'is false when user does not have the id' do
|
142
144
|
get :_user_has_id?, id: '23'
|
143
|
-
expect(assigns(:result)).to
|
145
|
+
expect(assigns(:result)).to be_falsey
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe '#user_has_attribute?' do
|
150
|
+
|
151
|
+
before { set_env_attribute(:department, 'HR') }
|
152
|
+
|
153
|
+
it 'is true when the user has the attribute and value' do
|
154
|
+
get :_user_has_attribute?, attr: :department, value: 'HR'
|
155
|
+
expect(assigns(:result)).to be_truthy
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'is false when the user doesnt have the attribute and/or value' do
|
159
|
+
get :_user_has_attribute?, attr: :department, value: 'QA'
|
160
|
+
expect(assigns(:result)).to be_falsey
|
144
161
|
end
|
145
162
|
end
|
146
163
|
end
|
@@ -10,6 +10,8 @@ class FiltersTestController < ApplicationController
|
|
10
10
|
before_action(only: :_require_id) { |c| c.require_id params[:id].to_i }
|
11
11
|
before_action(only: :_require_group_or_id) { |c| c.require_group_or_id params[:groups], params[:id].to_i }
|
12
12
|
before_action :use_attributes_if_available, only: :_use_attributes_if_available
|
13
|
+
before_action(only: :_require_attribute) { |c| c.require_attribute params[:attr], params[:value] }
|
14
|
+
before_action(only: :_require_group_or_attribute) { |c| c.require_group_or_attribute params[:groups], params[:attr], params[:value] }
|
13
15
|
|
14
16
|
def _require_login
|
15
17
|
render :dummy
|
@@ -34,4 +36,12 @@ class FiltersTestController < ApplicationController
|
|
34
36
|
def _use_attributes_if_available
|
35
37
|
render :dummy
|
36
38
|
end
|
39
|
+
|
40
|
+
def _require_attribute
|
41
|
+
render :dummy
|
42
|
+
end
|
43
|
+
|
44
|
+
def _require_group_or_attribute
|
45
|
+
render :dummy
|
46
|
+
end
|
37
47
|
end
|
@@ -13,7 +13,7 @@ Dummy::Application.configure do
|
|
13
13
|
config.eager_load = false
|
14
14
|
|
15
15
|
# Configure static asset server for tests with Cache-Control for performance.
|
16
|
-
config.
|
16
|
+
config.serve_static_files = true
|
17
17
|
config.static_cache_control = "public, max-age=3600"
|
18
18
|
|
19
19
|
# Show full error reports and disable caching.
|
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|