ucb_rails_user 4.0.5 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16591e2634ccad69a102f688132f754064005db006c45a1cdc59a66f186e299a
4
- data.tar.gz: 197103ec64e41e156973745bd90cf810c6ac85b1d0e945395fb300d322326f0c
3
+ metadata.gz: 69d322a97e81f8ca73eeaf2ed27dda97091f9cb60adca63840880c40098cc835
4
+ data.tar.gz: 9ee6320543f525fe409fe221ab4462c118be3cd72ed08b248661057eae882767
5
5
  SHA512:
6
- metadata.gz: 66e533e5bcf094769bd727ef8e9c651b9e2b3720a82ab36ebcdd0e27f5403db745fe44af8931ee68295edd95cc071771cd65014123a2b972125617b14934bf14
7
- data.tar.gz: 1031c24d8efe19130e8f8f4b6e961b7ef15447f27c7b0e35da5940979d848015f4099a7a7d8d41b24a921311130a87965349db2f39d314b08dcea8d74cb67891
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.
@@ -18,16 +18,21 @@ var addDatatablesToSearchResults = function () {
18
18
  }
19
19
 
20
20
  var addDatatablesToUsersTable = function () {
21
+ var unsorted_columns = $('.ucb-rails-users-table th.unsorted').map((i, e) => $(e).index()).toArray()
22
+ if (unsorted_columns === []) {
23
+ var unsorted_columns = $(".ucb-rails-users-table th:contains('Edit'),.ucb-rails-users-table th:contains('Delete')").map((i, e) => $(e).index()).toArray()
24
+ }
25
+
21
26
  $('.ucb-rails-users-table').dataTable({
22
27
  searching: true,
23
28
  order: [[ 3, "asc" ]],
24
29
  columnDefs: [ {
25
- targets: [8, 9],
30
+ targets: unsorted_columns,
26
31
  orderable: false
27
32
  }],
28
33
  })
29
34
  var addNewHtml = '&nbsp;&nbsp;<a href="/admin/users/new" class="btn btn-primary">Add New</a>'
30
- $('#DataTables_Table_0_filter').append(addNewHtml)
35
+ $('.ucb-rails-users-table-wrapper #DataTables_Table_0_filter').append(addNewHtml)
31
36
  }
32
37
 
33
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 User class should go into
5
- # UserConcerns. This will make it much easier for host apps to customize
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
+
@@ -2,7 +2,7 @@
2
2
  %h1
3
3
  Users
4
4
 
5
- .table-responsive
5
+ .table-responsive.ucb-rails-users-table-wrapper
6
6
  %table.table.table-striped.table-bordered.table-hover.ucb-rails-users-table
7
7
  %thead
8
8
  %tr
@@ -14,8 +14,8 @@
14
14
  %th.dt Last Login
15
15
  %th UID
16
16
  %th Employee ID
17
- %th.min Edit
18
- %th.min Delete
17
+ %th.min.unsorted Edit
18
+ %th.min.unsorted Delete
19
19
  %tbody.highlight
20
20
  = render partial: "ucb_rails_user/users/user", collection: @users
21
21
 
@@ -1,3 +1,3 @@
1
1
  module UcbRailsUser
2
- VERSION = '4.0.5'
2
+ VERSION = '4.1.0'
3
3
  end
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.5
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: 2021-03-29 00:00:00.000000000 Z
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.0'
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.0'
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: puma
149
+ name: faraday
130
150
  requirement: !ruby/object:Gem::Requirement
131
151
  requirements:
132
152
  - - "~>"
133
153
  - !ruby/object:Gem::Version
134
- version: '4.3'
135
- type: :development
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: '4.3'
161
+ version: '1.0'
142
162
  - !ruby/object:Gem::Dependency
143
- name: sqlite3
163
+ name: puma
144
164
  requirement: !ruby/object:Gem::Requirement
145
165
  requirements:
146
166
  - - "~>"
147
167
  - !ruby/object:Gem::Version
148
- version: '1.3'
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: '1.3'
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: '1.4'
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: '3.5'
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: '3.5'
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.2
389
+ rubygems_version: 3.1.4
360
390
  signing_key:
361
391
  specification_version: 4
362
392
  summary: Rails engine for UCB user accounts