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

pulibrary / tigerdata-app / 7291b10e-eaa3-4284-9371-5a980ceebf59

24 Nov 2025 07:18PM UTC coverage: 87.613% (-3.7%) from 91.333%
7291b10e-eaa3-4284-9371-5a980ceebf59

push

circleci

web-flow
Adds breadcrumb to Wizard (#2231)

Adds the breadcrumb to the Wizard and the functionality to allow the
user to save their changes before leaving the Wizard when clicking on
the "Dashboard" link in the breadcrumbs.

Closes #2102

5 of 12 new or added lines in 11 files covered. (41.67%)

904 existing lines in 36 files now uncovered.

2801 of 3197 relevant lines covered (87.61%)

360.23 hits per line

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

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

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

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

11
  paginates_per 100
4✔
12

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

15
  attr_accessor :mediaflux_session
4✔
16

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

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

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

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

61
  def mediaflux_login(token, session)
4✔
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
4✔
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)
4✔
UNCOV
87
    self.given_name = extra_cas_info.givenname
7✔
UNCOV
88
    self.family_name =  extra_cas_info.sn
7✔
UNCOV
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
4✔
95
    return uid if given_name.blank? && family_name.blank?
225✔
96

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

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

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

114
  def developer?
4✔
UNCOV
115
    return true if developer
2✔
UNCOV
116
    super
1✔
117
  end
118

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

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

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

UNCOV
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)
4✔
152
    # The return value _must_ have at least two elements since the serialize_from_session() requires
153
    # two arguments (see below)
154
    [record.uid, ""]
187✔
155
  end
156

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

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

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

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

191
  private
4✔
192

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

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