ncs_navigator_authority 0.0.2
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.
- data/.gitignore +5 -0
- data/.rvmrc +3 -0
- data/Gemfile +4 -0
- data/Rakefile +8 -0
- data/build.yaml +4 -0
- data/buildfile +7 -0
- data/lib/ncs_navigator/.DS_Store +0 -0
- data/lib/ncs_navigator/authorization.rb +7 -0
- data/lib/ncs_navigator/authorization/core.rb +3 -0
- data/lib/ncs_navigator/authorization/core/authority.rb +84 -0
- data/lib/ncs_navigator/authorization/psc.rb +3 -0
- data/lib/ncs_navigator/authorization/psc/authority.rb +193 -0
- data/lib/ncs_navigator/authorization/staff_portal.rb +6 -0
- data/lib/ncs_navigator/authorization/staff_portal/aker_token.rb +26 -0
- data/lib/ncs_navigator/authorization/staff_portal/client.rb +8 -0
- data/lib/ncs_navigator/authorization/staff_portal/connection.rb +33 -0
- data/lib/ncs_navigator/authorization/staff_portal/http_basic.rb +16 -0
- data/lib/ncs_navigator/authorization/version.rb +5 -0
- data/ncs_navigator_authority.gemspec +34 -0
- data/spec/fixtures/.DS_Store +0 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/core/unknown_user.yml +32 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/core/user.yml +32 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/all_users.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/empty_users_by_role.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/empty_users_by_search_criteria.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/unknown_user.yml +32 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/user_by_numeric_id.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/user_by_username.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_first_name.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_first_or_last_name.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_first_or_last_or_user_name.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_first_or_user_name.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_last_name.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_last_or_user_name.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_role.yml +34 -0
- data/spec/fixtures/vcr_cassettes/staff_portal/psc/users_by_username.yml +34 -0
- data/spec/navigator.ini +118 -0
- data/spec/ncs_navigator/.DS_Store +0 -0
- data/spec/ncs_navigator/authorization/core/authority_spec.rb +69 -0
- data/spec/ncs_navigator/authorization/psc/authority_spec.rb +292 -0
- data/spec/ncs_navigator/authorization/psc/role_mapping_spec.rb +99 -0
- data/spec/ncs_navigator/authorization/staff_portal/aker_token_spec.rb +36 -0
- data/spec/ncs_navigator/authorization/staff_portal/http_basic_spec.rb +17 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/vcr_setup.rb +7 -0
- metadata +257 -0
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/build.yaml
ADDED
data/buildfile
ADDED
Binary file
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'ncs_navigator/configuration'
|
2
|
+
module NcsNavigator::Authorization::Core
|
3
|
+
class Authority
|
4
|
+
def initialize(ignored_config=nil)
|
5
|
+
@groups = {}
|
6
|
+
@portal = :NCSNavigator
|
7
|
+
end
|
8
|
+
|
9
|
+
def amplify!(user)
|
10
|
+
base = user(user)
|
11
|
+
return user unless base
|
12
|
+
user.merge!(base)
|
13
|
+
end
|
14
|
+
|
15
|
+
def user(user)
|
16
|
+
staff = get_staff(user)
|
17
|
+
if staff
|
18
|
+
u = Aker::User.new(user.username)
|
19
|
+
u.portals << @portal
|
20
|
+
attributes = ["first_name", "last_name", "email"]
|
21
|
+
attributes.each do |a|
|
22
|
+
setter = "#{a}="
|
23
|
+
if u.respond_to?(setter)
|
24
|
+
u.send(setter, staff[a])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
u.identifiers[:staff_id] = staff["staff_id"]
|
28
|
+
groups = staff['roles'].collect do |role|
|
29
|
+
role['name']
|
30
|
+
end
|
31
|
+
|
32
|
+
if groups
|
33
|
+
u.group_memberships(@portal).concat(load_group_memberships(@portal, groups))
|
34
|
+
end
|
35
|
+
u
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def staff_portal_uri
|
44
|
+
NcsNavigator.configuration.staff_portal_uri
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_connection(user)
|
48
|
+
connection = staff_portal_client(user).connection
|
49
|
+
end
|
50
|
+
|
51
|
+
def staff_portal_client(user)
|
52
|
+
NcsNavigator::Authorization::StaffPortal::Client.new(staff_portal_uri, :authenticator => create_authenticator(user))
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_authenticator(user)
|
56
|
+
{ :token => lambda { user.cas_proxy_ticket(staff_portal_uri) } }
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_group_memberships(portal, group_data)
|
60
|
+
group_data.collect do |group|
|
61
|
+
Aker::GroupMembership.new(find_or_create_group(portal, group))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_or_create_group(portal, group_name)
|
66
|
+
existing = (@groups[portal] ||= []).collect { |top|
|
67
|
+
top.find { |g| g.name == group_name }
|
68
|
+
}.compact.first
|
69
|
+
return existing if existing
|
70
|
+
@groups[portal] << Aker::Group.new(group_name)
|
71
|
+
@groups[portal].last
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_staff(user)
|
75
|
+
connection = get_connection(user)
|
76
|
+
response = connection.get '/staff/' << user.username << '.json'
|
77
|
+
if response.status == 200
|
78
|
+
response.body
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'ncs_navigator/configuration'
|
2
|
+
module NcsNavigator::Authorization::Psc
|
3
|
+
class Authority
|
4
|
+
def initialize(ignored_config=nil)
|
5
|
+
@staff_portal_connection ||= staff_portal_client.connection
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_user_by_username(username, role_detail_level)
|
9
|
+
user(username)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_user_by_id(id, role_detail_level)
|
13
|
+
user(id)
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_users_by_role(role_name)
|
17
|
+
users_hash(get_users_collection_by_role(role_name))
|
18
|
+
end
|
19
|
+
|
20
|
+
def search_users(criteria)
|
21
|
+
users_hash(get_users_by_search_criteria(criteria))
|
22
|
+
end
|
23
|
+
|
24
|
+
def user(staff)
|
25
|
+
user_hash(get_user_by_username_or_id(staff))
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def users_hash(users)
|
31
|
+
users_hash = []
|
32
|
+
users.each do |u|
|
33
|
+
users_hash << user_hash(u)
|
34
|
+
end
|
35
|
+
users_hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def user_hash(staff)
|
39
|
+
return nil unless staff
|
40
|
+
{
|
41
|
+
:username => staff["username"],
|
42
|
+
:id => staff["numeric_id"],
|
43
|
+
:email_address => staff["email"],
|
44
|
+
:first_name => staff["first_name"],
|
45
|
+
:last_name => staff["last_name"],
|
46
|
+
:roles => roles_hash(staff["roles"].collect {|role| role['name']})
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def roles_hash(roles)
|
51
|
+
roles_hash = {}
|
52
|
+
roles.each do |role|
|
53
|
+
roles_hash.merge!(generate_roles_hash(role))
|
54
|
+
end
|
55
|
+
roles_hash
|
56
|
+
end
|
57
|
+
|
58
|
+
def generate_roles_hash(sp_role)
|
59
|
+
roles = {}
|
60
|
+
role_mappings = RoleMapping.staff_portal_to_psc(sp_role)
|
61
|
+
role_mappings.each do |role|
|
62
|
+
roles[role] = true
|
63
|
+
end
|
64
|
+
roles
|
65
|
+
end
|
66
|
+
|
67
|
+
def staff_portal_client
|
68
|
+
NcsNavigator::Authorization::StaffPortal::Client.new(NcsNavigator.configuration.staff_portal_uri, :authenticator => create_authenticator)
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_authenticator
|
72
|
+
{ :basic => ["psc_application", NcsNavigator.configuration.staff_portal['psc_user_password']] }
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_staff(url)
|
76
|
+
response = @staff_portal_connection.get url
|
77
|
+
if response.status == 200
|
78
|
+
response.body
|
79
|
+
else
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_user_by_username_or_id(staff)
|
85
|
+
url = '/staff/' << staff.to_s << '.json'
|
86
|
+
get_staff(url)
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_users_collection_by_role(psc_role)
|
90
|
+
roles = RoleMapping.psc_to_staff_portal(psc_role)
|
91
|
+
return roles if roles.empty?
|
92
|
+
query = 'role[]='
|
93
|
+
roles.each_with_index do |r, i|
|
94
|
+
query << r
|
95
|
+
unless r == roles.last
|
96
|
+
query << '&role[]='
|
97
|
+
end
|
98
|
+
end
|
99
|
+
url = '/users.json?' << query
|
100
|
+
get_staff(url)
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_users_by_search_criteria(criteria)
|
104
|
+
url = '/users.json'
|
105
|
+
unless criteria.empty?
|
106
|
+
url << "?" << construct_query(criteria)
|
107
|
+
end
|
108
|
+
get_staff(url)
|
109
|
+
end
|
110
|
+
|
111
|
+
def construct_query(criteria)
|
112
|
+
operator = "&"
|
113
|
+
if criteria.has_key?(:first_name_substring)
|
114
|
+
query = get_search_query("first_name", criteria[:first_name_substring])
|
115
|
+
if criteria.has_key?(:last_name_substring)
|
116
|
+
query << operator
|
117
|
+
query << get_search_query("last_name", criteria[:last_name_substring])
|
118
|
+
end
|
119
|
+
if criteria.has_key?(:username_substring)
|
120
|
+
query << operator
|
121
|
+
query << get_search_query("username", criteria[:username_substring])
|
122
|
+
end
|
123
|
+
elsif criteria.has_key?(:last_name_substring)
|
124
|
+
query = get_search_query("last_name", criteria[:last_name_substring])
|
125
|
+
if criteria.has_key?(:username_substring)
|
126
|
+
query << operator
|
127
|
+
query << get_search_query("username", criteria[:username_substring])
|
128
|
+
end
|
129
|
+
elsif criteria.has_key?(:username_substring)
|
130
|
+
query = get_search_query("username", criteria[:username_substring])
|
131
|
+
end
|
132
|
+
query << "&operator=OR" if criteria.size > 1
|
133
|
+
query
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_search_query(key, value)
|
137
|
+
query = "#{key}=" << value
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class RoleMapping
|
142
|
+
def self.psc_to_staff_portal(psc_role)
|
143
|
+
roles = [];
|
144
|
+
case psc_role
|
145
|
+
when :study_calendar_template_builder, :study_creator, :study_qa_manager, :study_site_participation_administrator, :system_administrator,
|
146
|
+
:data_importer, :business_administrator, :person_and_organization_information_manager
|
147
|
+
roles << "System Administrator"
|
148
|
+
when :user_administrator
|
149
|
+
roles << "User Administrator"
|
150
|
+
when :study_team_administrator
|
151
|
+
roles << "Staff Supervisor"
|
152
|
+
when :data_reader
|
153
|
+
roles << "Data Reader"
|
154
|
+
when :subject_manager
|
155
|
+
roles << "Field Staff"
|
156
|
+
roles << "Phone Staff"
|
157
|
+
when :study_subject_calendar_manager
|
158
|
+
roles << "Field Staff"
|
159
|
+
roles << "Phone Staff"
|
160
|
+
roles << "Biological Specimen Collector"
|
161
|
+
end
|
162
|
+
roles
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.staff_portal_to_psc(sp_role)
|
166
|
+
roles = [];
|
167
|
+
case sp_role
|
168
|
+
when "System Administrator"
|
169
|
+
roles << :study_creator
|
170
|
+
roles << :study_calendar_template_builder
|
171
|
+
roles << :study_qa_manager
|
172
|
+
roles << :study_site_participation_administrator
|
173
|
+
roles << :system_administrator
|
174
|
+
roles << :data_importer
|
175
|
+
roles << :business_administrator
|
176
|
+
roles << :person_and_organization_information_manager
|
177
|
+
when "User Administrator"
|
178
|
+
roles << :user_administrator
|
179
|
+
when "Staff Supervisor"
|
180
|
+
roles << :study_team_administrator
|
181
|
+
when "Field Staff", "Phone Staff"
|
182
|
+
roles << :subject_manager
|
183
|
+
roles << :study_subject_calendar_manager
|
184
|
+
when "Biological Specimen Collector"
|
185
|
+
roles << :study_subject_calendar_manager
|
186
|
+
when "Data Reader"
|
187
|
+
roles << :data_reader
|
188
|
+
end
|
189
|
+
roles
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
module NcsNavigator::Authorization::StaffPortal
|
2
|
+
autoload :AkerToken, 'ncs_navigator/authorization/staff_portal/aker_token'
|
3
|
+
autoload :HttpBasic, 'ncs_navigator/authorization/staff_portal/http_basic'
|
4
|
+
autoload :Client, 'ncs_navigator/authorization/staff_portal/client'
|
5
|
+
autoload :Connection, 'ncs_navigator/authorization/staff_portal/connection'
|
6
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module NcsNavigator::Authorization::StaffPortal
|
4
|
+
class AkerToken < ::Faraday::Middleware
|
5
|
+
def initialize(app, token_or_creator)
|
6
|
+
@app = app
|
7
|
+
if token_or_creator.respond_to?(:call)
|
8
|
+
@token_creator = token_or_creator
|
9
|
+
else
|
10
|
+
@token_creator = lambda { token_or_creator }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
env[:request_headers]['Authorization'] = "CasProxy #{token}"
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def token
|
23
|
+
@token_creator.call
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_stack'
|
3
|
+
module NcsNavigator::Authorization::StaffPortal
|
4
|
+
class Connection < ::Faraday::Connection
|
5
|
+
def initialize(url, options)
|
6
|
+
super do |builder|
|
7
|
+
builder.use *authentication_middleware(options[:authenticator])
|
8
|
+
builder.request :json
|
9
|
+
builder.use FaradayStack::ResponseJSON, :content_type => 'application/json'
|
10
|
+
builder.adapter :net_http
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def authentication_middleware(authenticator)
|
17
|
+
unless authenticator
|
18
|
+
raise 'No authentication method specified. Please include the :authenticator option.'
|
19
|
+
end
|
20
|
+
|
21
|
+
kind = authenticator.keys.first
|
22
|
+
|
23
|
+
case kind
|
24
|
+
when :basic
|
25
|
+
[NcsNavigator::Authorization::StaffPortal::HttpBasic, *authenticator[kind]]
|
26
|
+
when :token
|
27
|
+
[NcsNavigator::Authorization::StaffPortal::AkerToken, authenticator[kind]]
|
28
|
+
else
|
29
|
+
raise "Unsupported authentication method #{kind.inspect}."
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module NcsNavigator::Authorization::StaffPortal
|
4
|
+
class HttpBasic
|
5
|
+
def initialize(app, username, password)
|
6
|
+
@app = app
|
7
|
+
@header_value = "Basic #{Base64.encode64([username, password].join(':')).strip}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
env[:request_headers]['Authorization'] = @header_value
|
12
|
+
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|