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

pulibrary / tigerdata-app / 1f9ee909-20b2-467d-b493-b5be4964430d

22 Oct 2025 04:57PM UTC coverage: 91.212%. Remained the same
1f9ee909-20b2-467d-b493-b5be4964430d

push

circleci

web-flow
Fixing flaky tests (#2080)

10 times out of 10 one of these tests would fail for me locally.

Really we just have to look at the page for something new so that we are
sure the controller action has finished before we check for something
that is not waiting.

2740 of 3004 relevant lines covered (91.21%)

755.12 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"
6✔
4
class User < ApplicationRecord
6✔
5
  # Include default devise modules. Others available are:
6
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
7
  devise :rememberable, :omniauthable
6✔
8

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

11
  paginates_per 100
6✔
12

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

15
  attr_accessor :mediaflux_session
6✔
16

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

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

35
  # Users that can be data managers
36
  def self.manager_users
6✔
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)
6✔
45
    Rails.logger.debug("!!!!!!! Clearing Mediaflux session !!!!!!!!")
6✔
46
    @mediaflux_session = nil
6✔
47
    session[:mediaflux_session] = nil
6✔
48
  end
49

50
  def mediaflux_from_session(session)
6✔
51
    logger.debug "Session Get #{session[:mediaflux_session]} cas: #{session[:active_web_user]}  user: #{uid}"
1,047✔
52
    if session[:mediaflux_session].blank?
1,047✔
53
      logger.debug("!!!! Creating a new session !!! #{uid}")
540✔
54
      session[:mediaflux_session] = SystemUser.mediaflux_session
540✔
55
      session[:active_web_user] = false
536✔
56
    end
57
    @active_web_user = session[:active_web_user]
1,043✔
58
    @mediaflux_session = session[:mediaflux_session]
1,043✔
59
  end
60

61
  def mediaflux_login(token, session)
6✔
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
6✔
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)
6✔
87
    self.given_name = extra_cas_info.givenname
14✔
88
    self.family_name =  extra_cas_info.sn
14✔
89
    self.display_name = extra_cas_info.pudisplayname
14✔
90
  end
91

92
  # Return the display name if it exists, otherwise return the uid
93
  # @return [String]
94
  def display_name_safe
6✔
95
    return uid if display_name.blank?
450✔
96

97
    "#{display_name} (#{uid})"
436✔
98
  end
99

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

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

114
  def developer?
6✔
115
    return true if developer
20✔
116
    super
18✔
117
  end
118

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

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

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

135
    !Rails.env.production? && (eligible_sponsor? && trainer?)
8✔
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)
6✔
152
    # The return value _must_ have at least two elements since the serialize_from_session() requires
153
    # two arguments (see below)
154
    [record.uid, ""]
570✔
155
  end
156

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

161
  # Fetches the most recent download jobs for the user
162
  def latest_downloads(limit: 10)
6✔
163
    @latest_downloads ||= begin
136✔
164
                            downloads = UserRequest.where(user_id: id).where(["completion_time > ?", 7.days.ago]).order(created_at: "DESC").limit(limit)
134✔
165
                            downloads.map{|download| UserRequestPresenter.new(download)}
138✔
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:)
6✔
172
    raise "User.update_user_roles called with for a user without a Mediaflux session" if user.mediaflux_session.nil?
2✔
173

174
    mediaflux_roles = mediaflux_roles(user:)
2✔
175
    update_developer_status(user:, mediaflux_roles:)
2✔
176
    update_sysadmin_status(user:, mediaflux_roles:)
2✔
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:)
6✔
184
    raise "User.mediaflux_roles called with for a user without a Mediaflux session" if user.mediaflux_session.nil?
136✔
185

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

191
  private
6✔
192

193
  def self.update_developer_status(user:, mediaflux_roles:)
6✔
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") ||
2✔
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
2✔
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}")
2✔
206
      user.developer = developer_now
2✔
207
      user.save!
2✔
208
    end
209
  end
210

211
  def self.update_sysadmin_status(user:, mediaflux_roles:)
6✔
212
    sysadmin_now = mediaflux_roles.include?("system-administrator")
2✔
213
    if user.sysadmin != sysadmin_now
2✔
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}")
2✔
216
      user.sysadmin = sysadmin_now
2✔
217
      user.save!
2✔
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