• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / tigerdata-app / 700664ce-9925-405e-8380-cada5d7c2e48

07 Nov 2025 06:12PM UTC coverage: 91.229% (-0.1%) from 91.357%
700664ce-9925-405e-8380-cada5d7c2e48

Pull #2168

circleci

bess
Refactoring to allow easier integration of the new LUX widget
The lux widget takes the name of the routine to call when the input changes.  Making the url integrated with the page will allow us to more easily call the lookup routine

refs #2083
Pull Request #2168: Refactoring to allow easier integration of the new LUX widget

2850 of 3124 relevant lines covered (91.23%)

538.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.86
/app/models/user.rb
1
# frozen_string_literal: true
2

3
require "csv"
5✔
4
class User < ApplicationRecord
5✔
5
  # Include default devise modules. Others available are:
6
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
7
  devise :rememberable, :omniauthable
5✔
8

9
  has_many :user_requests, dependent: :destroy
5✔
10

11
  paginates_per 100
5✔
12

13
  USER_REGISTRATION_LIST = Rails.root.join("data", "user_registration_list_#{Rails.env}.csv")
5✔
14

15
  attr_accessor :mediaflux_session
5✔
16

17
  def self.from_cas(access_token)
5✔
18
    user = User.find_by(provider: access_token.provider, uid: access_token.uid)
9✔
19
    if user.present? && user.given_name.nil? # fix any users that do not have the name information loaded
9✔
20
      user.initialize_name_values(access_token.extra)
7✔
21
      user.save
7✔
22
    end
23
    user
9✔
24
  end
25

26
  # Users that can be project sponsors
27
  def self.sponsor_users
5✔
28
    if Rails.env.development? || Rails.env.staging?
2✔
29
      User.where(eligible_sponsor: true).or(User.where(developer: true))
1✔
30
    else
31
      User.where(eligible_sponsor: true)
1✔
32
    end
33
  end
34

35
  # Users that can be data managers
36
  def self.manager_users
5✔
37
    if Rails.env.development? || Rails.env.staging?
×
38
      User.where(eligible_manager: true).or(User.where(developer: true))
×
39
    else
40
      User.where(eligible_manager: true)
×
41
    end
42
  end
43

44
  def clear_mediaflux_session(session)
5✔
45
    Rails.logger.debug("!!!!!!! Clearing Mediaflux session !!!!!!!!")
3✔
46
    @mediaflux_session = nil
3✔
47
    session[:mediaflux_session] = nil
3✔
48
  end
49

50
  def mediaflux_from_session(session)
5✔
51
    logger.debug "Session Get #{session[:mediaflux_session]} cas: #{session[:active_web_user]}  user: #{uid}"
531✔
52
    if session[:mediaflux_session].blank?
531✔
53
      logger.debug("!!!! Creating a new session !!! #{uid}")
272✔
54
      session[:mediaflux_session] = SystemUser.mediaflux_session
272✔
55
      session[:active_web_user] = false
270✔
56
    end
57
    @active_web_user = session[:active_web_user]
529✔
58
    @mediaflux_session = session[:mediaflux_session]
529✔
59
  end
60

61
  def mediaflux_login(token, session)
5✔
62
    logger.debug("mediaflux session created for #{uid}")
×
63
    logon_request = Mediaflux::LogonRequest.new(identity_token: token, token_type: "cas")
×
64
    if logon_request.error?
×
65
      raise "Invalid Logon #{logon_request.response_error}"
×
66
    end
67
    @mediaflux_session = logon_request.session_token
×
68
    @active_web_user = true
×
69
    session[:mediaflux_session] = @mediaflux_session
×
70
    session[:active_web_user] = @active_web_user
×
71
    logger.debug "Login Session #{session[:mediaflux_session]} cas: #{session[:active_web_user]}  user: #{uid}"
×
72

73
    User.update_user_roles(user: self)
×
74
  end
75

76
  def terminate_mediaflux_session
5✔
77
    return if @mediaflux_session.nil? # nothing to terminate
×
78
    logger.debug "!!!! Terminating mediaflux session"
×
79

80
    Mediaflux::LogoutRequest.new(session_token: @mediaflux_session).response_body
×
81
    @mediaflux_session = nil
×
82
  end
83

84
  # Initialize the name values from the CAS information.
85
  # Our name fields do not match their name fields, so we need to translate.
86
  def initialize_name_values(extra_cas_info)
5✔
87
    self.given_name = extra_cas_info.givenname
7✔
88
    self.family_name =  extra_cas_info.sn
7✔
89
    self.display_name = extra_cas_info.pudisplayname
7✔
90
  end
91

92
  # Return the display name if it exists, otherwise return the uid
93
  # @return [String]
94
  def display_name_safe
5✔
95
    return uid if given_name.blank? && family_name.blank?
459✔
96

97
    [given_name, family_name, "(#{uid})"].compact.join(" ")
452✔
98
  end
99

100
  # Is this user eligible to be a data sponsor in this environment?
101
  # @return [Boolean]
102
  def eligible_sponsor?
5✔
103
    return true if developer
49✔
104
    super
48✔
105
  end
106

107
  # Is this user eligible to be a data manger in this environment?
108
  # @return [Boolean]
109
  def eligible_manager?
5✔
110
    return true if developer
19✔
111
    super
18✔
112
  end
113

114
  def developer?
5✔
115
    return true if developer
12✔
116
    super
11✔
117
  end
118

119
  # Is this user eligible to be a data user in this environment?
120
  # @return [Boolean]
121
  def eligible_data_user?
5✔
122
    return true if developer
23✔
123
    return true if !eligible_sponsor? && !eligible_manager
23✔
124
  end
125

126
  # Is this user eligible to be a sysadmin in this environment?
127
  # @return [Boolean]
128
  def eligible_sysadmin?
5✔
129
    (!Rails.env.production? && (developer || sysadmin)) || (Rails.env.production? && sysadmin)
342✔
130
  end
131

132
  def eligible_to_create_new?
5✔
133
    return true if eligible_sysadmin?
6✔
134

135
    !Rails.env.production? && (eligible_sponsor? && trainer?)
4✔
136
  end
137

138
  # Methods serialize_into_session() and serialize_from_session() are called by Warden/Devise
139
  # to calculate what information will be stored in the session and to serialize an object
140
  # back from the session.
141
  #
142
  # By default Warden/Devise store the database ID of the record (e.g. User.id) but this causes
143
  # problems if we repopulate our User table and the IDs change. The implementation provided below
144
  # uses the User.uid field (which is unique, does not change, and it's required) as the value to
145
  # store in the session to prevent this issue.
146
  #
147
  # References:
148
  #   https://stackoverflow.com/questions/23597718/what-is-the-warden-data-in-a-rails-devise-session-composed-of/23683925#23683925
149
  #   https://web.archive.org/web/20211028103224/https://tadas-s.github.io/ruby-on-rails/2020/08/02/devise-serialize-into-session-trick/
150
  #   https://github.com/wardencommunity/warden/wiki/Setup
151
  def self.serialize_into_session(record)
5✔
152
    # The return value _must_ have at least two elements since the serialize_from_session() requires
153
    # two arguments (see below)
154
    [record.uid, ""]
287✔
155
  end
156

157
  def self.serialize_from_session(key, _salt, _opts = {})
5✔
158
    User.where(uid: key)&.first
350✔
159
  end
160

161
  # Fetches the most recent download jobs for the user
162
  def latest_downloads(limit: 10)
5✔
163
    @latest_downloads ||= begin
68✔
164
                            downloads = UserRequest.where(user_id: id).where(["completion_time > ?", 7.days.ago]).order(created_at: "DESC").limit(limit)
67✔
165
                            downloads.map{|download| UserRequestPresenter.new(download)}
69✔
166
                          end
167
  end
168

169
  # Updates the user's roles (sys admin, developer) depending on the information on Mediaflux.
170
  # This method is meant to be used only for the current logged in user since the roles depend on the Mediaflux session.
171
  def self.update_user_roles(user:)
5✔
172
    raise "User.update_user_roles called with for a user without a Mediaflux session" if user.mediaflux_session.nil?
1✔
173

174
    mediaflux_roles = mediaflux_roles(user:)
1✔
175
    update_developer_status(user:, mediaflux_roles:)
1✔
176
    update_sysadmin_status(user:, mediaflux_roles:)
1✔
177
  rescue => ex
178
    Rails.logger.error("Error updating roles for user (id: #{user.id}) status, error: #{ex.message}")
×
179
  end
180

181
  # Returns the roles in Mediaflux for the user in the session.
182
  # This method is meant to be used only for the current logged in user since the roles depend on the Mediaflux session.
183
  def self.mediaflux_roles(user:)
5✔
184
    raise "User.mediaflux_roles called with for a user without a Mediaflux session" if user.mediaflux_session.nil?
68✔
185

186
    request = Mediaflux::ActorSelfDescribeRequest.new(session_token: user.mediaflux_session)
67✔
187
    request.resolve
67✔
188
    request.roles
67✔
189
  end
190

191
  private
5✔
192

193
  def self.update_developer_status(user:, mediaflux_roles:)
5✔
194
    # TODO: Figure out why the role name is different in staging from production:
195
    #   production:   "pu-smb-group:PU:tigerdata:librarydevelopers"
196
    #   staging:      "pu-oit-group:PU:tigerdata:librarydevelopers"
197
    #   development:  "pu-lib:developer"
198
    #   test:         "system-administrator"
199
    developer_now = mediaflux_roles.include?("pu-smb-group:PU:tigerdata:librarydevelopers") ||
1✔
200
      mediaflux_roles.include?("pu-oit-group:PU:tigerdata:librarydevelopers") ||
201
      mediaflux_roles.include?("pu-lib:developer") ||
202
      mediaflux_roles.include?("system-administrator")
203
    if user.developer != developer_now
1✔
204
      # Only update the record in the database if there is a change
205
      Rails.logger.info("Updating developer role for user #{user.id} to #{developer_now}")
1✔
206
      user.developer = developer_now
1✔
207
      user.save!
1✔
208
    end
209
  end
210

211
  def self.update_sysadmin_status(user:, mediaflux_roles:)
5✔
212
    sysadmin_now = mediaflux_roles.include?("system-administrator")
1✔
213
    if user.sysadmin != sysadmin_now
1✔
214
      # Only update the record in the database if there is a change
215
      Rails.logger.info("Updating sysadmin role for user #{user.id} to #{sysadmin_now}")
1✔
216
      user.sysadmin = sysadmin_now
1✔
217
      user.save!
1✔
218
    end
219
  end
220
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc