ucb_rails_user 4.0.7 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -0
- data/app/assets/javascripts/ucb_rails_user/ucb_rails_user.js +1 -1
- data/app/models/ucb_rails_user/impersonation.rb +2 -2
- data/app/models/ucb_rails_user/user_session_manager/in_uc_path_add_to_users_table.rb +39 -0
- data/app/models/ucb_rails_user/user_uc_path_service.rb +97 -0
- data/app/views/ucb_rails_user/users/index.html.haml +1 -1
- data/lib/ucb_rails_user/version.rb +1 -1
- metadata +49 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69d322a97e81f8ca73eeaf2ed27dda97091f9cb60adca63840880c40098cc835
|
4
|
+
data.tar.gz: 9ee6320543f525fe409fe221ab4462c118be3cd72ed08b248661057eae882767
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4ee1dc80e260cedd5e5cfbcb7c7de1cb493a158225926ab586bd8dbfa33ac86ca9f1dbfc213da91b11128fa59a15663a68aedca5a4aa8a118f748484afd99db
|
7
|
+
data.tar.gz: 54a0492f88ea47ca8a6d09a72408e046bf945618a8ad2967fdf675ed52ff89ab49f4a884dcc91805785f30eb533ddc3d257beabe8eacb8c40c243d2ba89f4c54
|
data/README.md
CHANGED
@@ -105,6 +105,20 @@ For example, if the admin screens for your app are under the `/backend` path rat
|
|
105
105
|
resources :users, controller: "ucb_rails_user/users", path: "backend/users", as: :backend_users
|
106
106
|
```
|
107
107
|
|
108
|
+
## Session Managers
|
109
|
+
|
110
|
+
Authentication during login is handled by UCB's central auth system and this gem uses the [omniauth-cas](https://github.com/dlindahl/omniauth-cas) to manage the handshake. Once that is completed, we're handed the LDAP uid of the authenticated user, and, by default, this gem will attempt to pull the user's employee data and create or update a `User` record for them in the local database.
|
111
|
+
|
112
|
+
This behavior can be customized by writing your own user session manager. There are two steps to do this:
|
113
|
+
|
114
|
+
1. Create a subclass of [`UcbRailsUser::UserSessionManager::Base`](https://github.com/ucb-ist-eas/ucb_rails_user/blob/main/app/models/ucb_rails_user/user_session_manager/base.rb). At a minimum you need to implement a `login` method that accepts the user's LDAP uid and returns a `User` instance (or raises an error if the process fails), and a `current_user` method that returns the `User` instance for the currently-logged-in user. [Several implementations](https://github.com/ucb-ist-eas/ucb_rails_user/tree/main/app/models/ucb_rails_user/user_session_manager) are included so you can look to these to base yours off of.
|
115
|
+
|
116
|
+
1. Open `config/initializers/ucb_rails_user.rb` in your host app and change the `user_session_manager` config setting to the class your custom implementation:
|
117
|
+
|
118
|
+
```
|
119
|
+
config.user_session_manager = "MyApp::MyCustomUserSessionManager"
|
120
|
+
```
|
121
|
+
|
108
122
|
## User Impersonation
|
109
123
|
|
110
124
|
The impersonation feature allows admins to be logged in as a different user in the system. This is useful when trying to diagnose data-specific problems, as the admin can see exactly what the user sees.
|
@@ -32,7 +32,7 @@ var addDatatablesToUsersTable = function () {
|
|
32
32
|
}],
|
33
33
|
})
|
34
34
|
var addNewHtml = ' <a href="/admin/users/new" class="btn btn-primary">Add New</a>'
|
35
|
-
$('#DataTables_Table_0_filter').append(addNewHtml)
|
35
|
+
$('.ucb-rails-users-table-wrapper #DataTables_Table_0_filter').append(addNewHtml)
|
36
36
|
}
|
37
37
|
|
38
38
|
var resetImpersonateButton = function() {
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class UcbRailsUser::Impersonation < ApplicationRecord
|
2
2
|
include UcbRailsUser::Concerns::ImpersonationConcerns
|
3
3
|
|
4
|
-
# Don't add anything more here - any logic for the
|
5
|
-
#
|
4
|
+
# Don't add anything more here - any logic for the Impersonation class should go into
|
5
|
+
# ImpersonationConcerns. This will make it much easier for host apps to customize
|
6
6
|
# behavior if they need to
|
7
7
|
# http://guides.rubyonrails.org/engines.html#implementing-decorator-pattern-using-activesupport-concern
|
8
8
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Session manager that attempts to pull the user record from UCPath, and
|
2
|
+
# falls back to LDAP if needed
|
3
|
+
|
4
|
+
module UcbRailsUser
|
5
|
+
module UserSessionManager
|
6
|
+
|
7
|
+
class InUcPathAddToUsersTable < ActiveInUserTable
|
8
|
+
def login(uid)
|
9
|
+
self.uid = uid
|
10
|
+
|
11
|
+
# try UCPath first
|
12
|
+
user = safely_load_user_from_api do
|
13
|
+
UcbRailsUser::UserUcPathService.create_or_update_user_from_ldap_uid(self.uid)
|
14
|
+
end
|
15
|
+
|
16
|
+
# if that doesn't work, try LDAP
|
17
|
+
user ||= safely_load_user_from_api do
|
18
|
+
UcbRailsUser::UserLdapService.create_or_update_user_from_entry(people_ou_entry)
|
19
|
+
end
|
20
|
+
|
21
|
+
user&.tap do |u|
|
22
|
+
u&.touch(:last_login_at)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def safely_load_user_from_api(&block)
|
29
|
+
begin
|
30
|
+
user = block.call
|
31
|
+
rescue StandardError
|
32
|
+
user = nil
|
33
|
+
end
|
34
|
+
user
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "faraday"
|
2
|
+
|
3
|
+
class UcbRailsUser::UserUcPathService
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def create_or_update_user_from_ldap_uid(ldap_uid)
|
8
|
+
ucpath_entry = ucpath_client.fetch_employee_data(ldap_uid)
|
9
|
+
return nil unless ucpath_entry.present?
|
10
|
+
|
11
|
+
User.find_or_initialize_by(ldap_uid: ldap_uid).tap do |user|
|
12
|
+
name_entry = parse_name(ucpath_entry)
|
13
|
+
user.first_name = name_entry["givenName"]
|
14
|
+
user.last_name = name_entry["familyName"]
|
15
|
+
user.employee_id = ucpath_entry["identifiers"]&.detect do |id|
|
16
|
+
id["type"] == "hr-employee-id"
|
17
|
+
end&.fetch("id")
|
18
|
+
user.email = parse_email(ucpath_entry)
|
19
|
+
user.inactive_flag = false # any way to pull this from the API?
|
20
|
+
user.save!
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_name(entry)
|
25
|
+
return nil unless entry.present?
|
26
|
+
find_name_by_type(entry["names"], "PRF") ||
|
27
|
+
find_name_by_type(entry["names"], "PRI")
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_name_by_type(names, type)
|
31
|
+
names&.detect do |n|
|
32
|
+
n.dig("type", "code") == type
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_email(entry)
|
37
|
+
email_entry =
|
38
|
+
entry["emails"]&.detect do |email|
|
39
|
+
email["primary"] == true
|
40
|
+
end
|
41
|
+
email_entry ||= entry["emails"]&.first # if there's no primary email, grab whatever we can
|
42
|
+
email_entry&.fetch("emailAddress")
|
43
|
+
end
|
44
|
+
|
45
|
+
def ucpath_client
|
46
|
+
UcPathClient.new
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class UcPathClient
|
52
|
+
attr_reader :app_id, :app_key, :endpoint
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
credentials =
|
56
|
+
Rails.application.credentials.ucpath || Rails.application.credentials.hcm
|
57
|
+
@app_id = credentials&.fetch(:app_id)
|
58
|
+
@app_key = credentials&.fetch(:app_key)
|
59
|
+
@endpoint = credentials&.fetch(:endpoint)
|
60
|
+
end
|
61
|
+
|
62
|
+
def fetch_employee_data(ldap_uid)
|
63
|
+
if [app_id, app_key, endpoint].any?(&:blank?)
|
64
|
+
Rails.logger.warn missing_api_values_message
|
65
|
+
return nil
|
66
|
+
end
|
67
|
+
|
68
|
+
response =
|
69
|
+
Faraday.get("#{endpoint}/employees/#{ldap_uid}") do |req|
|
70
|
+
req.params["id-type"] = "campus-uid"
|
71
|
+
req.headers["Accept"] = "application/json"
|
72
|
+
req.headers["app_id"] = app_id
|
73
|
+
req.headers["app_key"] = app_key
|
74
|
+
end
|
75
|
+
parse_response(response)&.first
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def parse_response(response)
|
81
|
+
return nil if !response.success? || response.body.empty?
|
82
|
+
JSON.parse(response.body)&.fetch("response")
|
83
|
+
end
|
84
|
+
|
85
|
+
def missing_api_values_message
|
86
|
+
<<~END_MSG.strip
|
87
|
+
It looks like you're trying to use the preferred user name feature of
|
88
|
+
ucb_rails_user, but the host app has not provided all of the expected
|
89
|
+
credentials to access the UCPath API.
|
90
|
+
To resolve this, add an "hcm" section to the Rails credentials file of
|
91
|
+
the host app, and provide values for app_id, app_key, and endpoint.
|
92
|
+
END_MSG
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ucb_rails_user
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Downey
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2022-05-20 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rails
|
@@ -19,14 +19,34 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - ">"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '5.
|
22
|
+
version: '5.2'
|
23
|
+
- - "<"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '8.0'
|
23
26
|
type: :runtime
|
24
27
|
prerelease: false
|
25
28
|
version_requirements: !ruby/object:Gem::Requirement
|
26
29
|
requirements:
|
27
30
|
- - ">"
|
28
31
|
- !ruby/object:Gem::Version
|
29
|
-
version: '5.
|
32
|
+
version: '5.2'
|
33
|
+
- - "<"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '8.0'
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sprockets-rails
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
30
50
|
- !ruby/object:Gem::Dependency
|
31
51
|
name: haml
|
32
52
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,53 +146,61 @@ dependencies:
|
|
126
146
|
- !ruby/object:Gem::Version
|
127
147
|
version: '3.0'
|
128
148
|
- !ruby/object:Gem::Dependency
|
129
|
-
name:
|
149
|
+
name: faraday
|
130
150
|
requirement: !ruby/object:Gem::Requirement
|
131
151
|
requirements:
|
132
152
|
- - "~>"
|
133
153
|
- !ruby/object:Gem::Version
|
134
|
-
version: '
|
135
|
-
type: :
|
154
|
+
version: '1.0'
|
155
|
+
type: :runtime
|
136
156
|
prerelease: false
|
137
157
|
version_requirements: !ruby/object:Gem::Requirement
|
138
158
|
requirements:
|
139
159
|
- - "~>"
|
140
160
|
- !ruby/object:Gem::Version
|
141
|
-
version: '
|
161
|
+
version: '1.0'
|
142
162
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
163
|
+
name: puma
|
144
164
|
requirement: !ruby/object:Gem::Requirement
|
145
165
|
requirements:
|
146
166
|
- - "~>"
|
147
167
|
- !ruby/object:Gem::Version
|
148
|
-
version: '
|
149
|
-
- - "<"
|
150
|
-
- !ruby/object:Gem::Version
|
151
|
-
version: '1.4'
|
168
|
+
version: '5.6'
|
152
169
|
type: :development
|
153
170
|
prerelease: false
|
154
171
|
version_requirements: !ruby/object:Gem::Requirement
|
155
172
|
requirements:
|
156
173
|
- - "~>"
|
157
174
|
- !ruby/object:Gem::Version
|
158
|
-
version: '
|
159
|
-
|
175
|
+
version: '5.6'
|
176
|
+
- !ruby/object:Gem::Dependency
|
177
|
+
name: sqlite3
|
178
|
+
requirement: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
160
181
|
- !ruby/object:Gem::Version
|
161
|
-
version: '
|
182
|
+
version: '0'
|
183
|
+
type: :development
|
184
|
+
prerelease: false
|
185
|
+
version_requirements: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
162
190
|
- !ruby/object:Gem::Dependency
|
163
191
|
name: rspec-rails
|
164
192
|
requirement: !ruby/object:Gem::Requirement
|
165
193
|
requirements:
|
166
194
|
- - "~>"
|
167
195
|
- !ruby/object:Gem::Version
|
168
|
-
version: '
|
196
|
+
version: '5.0'
|
169
197
|
type: :development
|
170
198
|
prerelease: false
|
171
199
|
version_requirements: !ruby/object:Gem::Requirement
|
172
200
|
requirements:
|
173
201
|
- - "~>"
|
174
202
|
- !ruby/object:Gem::Version
|
175
|
-
version: '
|
203
|
+
version: '5.0'
|
176
204
|
- !ruby/object:Gem::Dependency
|
177
205
|
name: factory_bot_rails
|
178
206
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,8 +336,10 @@ files:
|
|
308
336
|
- app/models/ucb_rails_user/user_session_manager/base.rb
|
309
337
|
- app/models/ucb_rails_user/user_session_manager/in_people_ou.rb
|
310
338
|
- app/models/ucb_rails_user/user_session_manager/in_people_ou_add_to_users_table.rb
|
339
|
+
- app/models/ucb_rails_user/user_session_manager/in_uc_path_add_to_users_table.rb
|
311
340
|
- app/models/ucb_rails_user/user_session_manager/ldap_person_user_wrapper.rb
|
312
341
|
- app/models/ucb_rails_user/user_session_manager/test_session_manager.rb
|
342
|
+
- app/models/ucb_rails_user/user_uc_path_service.rb
|
313
343
|
- app/models/user.rb
|
314
344
|
- app/views/ucb_rails_user/home/logged_in.html.haml
|
315
345
|
- app/views/ucb_rails_user/home/not_logged_in.html.haml
|
@@ -356,7 +386,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
356
386
|
- !ruby/object:Gem::Version
|
357
387
|
version: '0'
|
358
388
|
requirements: []
|
359
|
-
rubygems_version: 3.1.
|
389
|
+
rubygems_version: 3.1.4
|
360
390
|
signing_key:
|
361
391
|
specification_version: 4
|
362
392
|
summary: Rails engine for UCB user accounts
|