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

pulibrary / pdc_describe / 9091a1ae-29be-458c-984a-339d213919c4

12 Dec 2024 07:41PM UTC coverage: 26.434% (-69.7%) from 96.113%
9091a1ae-29be-458c-984a-339d213919c4

Pull #2000

circleci

jrgriffiniii
Removing integration with ActiveStorage
Pull Request #2000: Bump actionpack from 7.2.1.1 to 7.2.2.1

945 of 3575 relevant lines covered (26.43%)

0.35 hits per line

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

38.73
/app/models/user.rb
1
# frozen_string_literal: true
2
require "csv"
1✔
3

4
# rubocop:disable Metrics/ClassLength
5
class User < ApplicationRecord
1✔
6
  rolify
1✔
7
  extend FriendlyId
1✔
8
  friendly_id :uid
1✔
9

10
  devise :rememberable, :omniauthable
1✔
11

12
  after_initialize :safe_uid_check
1✔
13

14
  # GroupOptions model extensible options set for Groups and Users
15
  has_many :group_options, dependent: :destroy
1✔
16
  has_many :group_messaging_options, -> { where(option_type: GroupOption::EMAIL_MESSAGES) }, class_name: "GroupOption", dependent: :destroy
1✔
17

18
  has_many :groups_with_options, through: :group_options, source: :group
1✔
19
  has_many :groups_with_messaging, through: :group_messaging_options, source: :group
1✔
20

21
  after_create :assign_default_role
1✔
22

23
  attr_accessor :just_created
1✔
24

25
  validate do |user|
1✔
26
    user.orcid&.strip!
1✔
27
    if user.orcid.present? && Orcid.invalid?(user.orcid)
1✔
28
      user.errors.add :base, "Invalid format for ORCID"
×
29
    end
30
  end
31

32
  def self.from_cas(access_token)
1✔
33
    user = User.find_by(uid: safe_uid(access_token.uid))
×
34
    if user.nil?
×
35
      user = new_from_cas(access_token)
×
36
    elsif user.provider.blank?
×
37
      user.update_with_cas(access_token)
×
38
    end
39
    user
×
40
  end
41

42
  # Create a new user with some basic information from CAS.
43
  def self.new_from_cas(access_token)
1✔
44
    user = User.new
×
45
    user.provider = access_token.provider
×
46
    user.uid = safe_uid(access_token.uid) # this is the netid
×
47
    user.email = User.email_from_access_token(access_token)
×
48
    user.given_name = access_token.extra.givenname || access_token.uid # Harriet
×
49
    user.family_name = access_token.extra.sn || access_token.uid # Tubman
×
50
    user.full_name = access_token.extra.displayname || access_token.uid # "Harriet Tubman"
×
51
    user.default_group_id = Group.default_for_department(access_token.extra.departmentnumber)&.id
×
52
    user.save!
×
53
    user
×
54
  end
55

56
  def self.safe_uid(uid)
1✔
57
    return uid if uid.blank?
1✔
58
    uid.gsub(/[^(0-9a-zA-Z_\-)]/, "_")
×
59
  end
60

61
  def self.email_from_access_token(access_token)
1✔
62
    if !access_token.extra.mail.nil?
×
63
      # For typical Princeton accounts the email comes on the `email` field
64
      access_token.extra.mail
×
65
    elsif User.looks_like_email_address?(access_token.extra.givenname)
×
66
      # For Guest Access Accounts (GAP) the email comes in the `givenname`
67
      access_token.extra.givenname
×
68
    end
69
  end
70

71
  def self.looks_like_email_address?(value)
1✔
72
    URI::MailTo::EMAIL_REGEXP.match?(value)
×
73
  end
74

75
  # Updates an existing User record with some information from CAS. This is useful
76
  # for records created before the user ever logged in (e.g. to grant them permissions
77
  # to groups).
78
  def update_with_cas(access_token)
1✔
79
    self.provider = access_token.provider
×
80
    self.email = User.email_from_access_token(access_token)
×
81
    self.given_name = access_token.extra.givenname || access_token.uid # Harriet
×
82
    self.family_name = access_token.extra.sn || access_token.uid # Tubman
×
83
    self.full_name = access_token.extra.displayname || access_token.uid # "Harriet Tubman"
×
84
    self.default_group_id ||= Group.default_for_department(access_token.extra.departmentnumber)&.id
×
85
    save!
×
86
  end
87

88
  # Creates a new user by uid. If the user already exists it returns the existing user.
89
  def self.new_for_uid(uid)
1✔
90
    user = User.find_by(uid:)
×
91
    if user.nil?
×
92
      user = User.new(uid:, email: "#{uid}@princeton.edu")
×
93
      user.save!
×
94
    end
95
    user
×
96
  end
97

98
  def self.new_super_admin(uid)
1✔
99
    user = new_for_uid(uid)
×
100
    user.add_role(:super_admin) unless user.has_role?(:super_admin)
×
101
    user.add_role(:group_admin) unless user.has_role?(:group_admin)
×
102
    user
×
103
  end
104

105
  # rubocop:disable Metrics/MethodLength
106
  def self.new_from_csv_params(csv_params)
1✔
107
    email = "#{csv_params['Net ID']}@princeton.edu"
×
108
    uid = csv_params["Net ID"]
×
109
    given_name = csv_params["First Name"]
×
110
    family_name = csv_params["Last Name"]
×
111
    full_name = "#{given_name} #{family_name}"
×
112
    orcid = csv_params["ORCID ID"]
×
113
    user = User.where(email:).first_or_create
×
114
    params_hash = {
115
      email:,
×
116
      uid:,
117
      orcid:,
118
      full_name: (full_name if user.full_name.blank?),
×
119
      family_name: (family_name if user.family_name.blank?),
×
120
      given_name: (given_name if user.given_name.blank?)
×
121
    }.compact
122

123
    user.update(params_hash)
×
124
    Rails.logger.info "Successfully created or updated #{user.email}"
×
125
    user
×
126
  end
127
  # rubocop:enable Metrics/MethodLength
128

129
  def self.create_users_from_csv(csv)
1✔
130
    users = []
×
131
    CSV.foreach(csv, headers: true) do |row|
×
132
      next if row["Net ID"] == "N/A"
×
133
      users << new_from_csv_params(row.to_hash)
×
134
    end
135
    users
×
136
  end
137

138
  # Creates the default users as indicated in the super_admin config file
139
  # and the default administrators and submitters for each group.
140
  # It only creates missing records, i.e. if the records already exist it
141
  # will not create a duplicate. It also does _not_ remove already configured
142
  # access to other groups.
143
  def self.create_default_users
1✔
144
    update_super_admins
×
145

146
    Group.find_each do |group|
×
147
      Rails.logger.info "Setting up admins for group #{group.title}"
×
148
      group.default_admins_list.each do |uid|
×
149
        user = User.new_for_uid(uid)
×
150
        user.add_role :group_admin, group
×
151
      end
152

153
      Rails.logger.info "Setting up submitters for group #{group.title}"
×
154
      group.default_submitters_list.each do |uid|
×
155
        user = User.new_for_uid(uid)
×
156
        user.add_role :submitter, group
×
157
      end
158
    end
159
  end
160

161
  def self.update_super_admins
1✔
162
    Rails.logger.info "Setting super administrators"
×
163
    Rails.configuration.super_admins.each do |uid|
×
164
      new_super_admin(uid)
×
165
    end
166
  end
167

168
  # Returns a string with the UID (netid) for all the users.
169
  # We use this string to power the JavaScript @mention functionality when adding messages to works.
170
  def self.all_uids_string
1✔
171
    User.all.map { |user| '"' + user.uid + '"' }.join(", ")
×
172
  end
173

174
  ##
175
  # Is this user a super_admin? super_admins automatically get admin status in every
176
  # group, and they can make new groups.
177
  # @return [Boolean]
178
  def super_admin?
1✔
179
    has_role? :super_admin
2✔
180
  rescue => ex
181
    Rails.logger.error("Unexpected error checking super_admin: #{ex}")
×
182
    false
×
183
  end
184

185
  # Returns a display name that always has a value
186
  # This is needed because we have records in the Users table that are created automatically
187
  # in which the only value we have for sure its their uid (aka NetID).
188
  def given_name_safe
1✔
189
    given_name.presence || uid
×
190
  end
191

192
  # Returns a full name that always has a value
193
  # This is needed because we have records in the Users table that are created automatically
194
  # in which the only value we have for sure its their uid (aka NetID).
195
  def full_name_safe
1✔
196
    full_name&.strip.presence || uid
×
197
  end
198

199
  def moderator?
1✔
200
    admin_groups.count > 0
×
201
  end
202

203
  # Returns a reference to the user's default group.
204
  def default_group
1✔
205
    if default_group_id.nil?
3✔
206
      Group.default
×
207
    else
208
      Group.find(default_group_id)
3✔
209
    end
210
  end
211

212
  # True if the user can submit datasets to the group
213
  def can_submit?(group)
1✔
214
    return true if super_admin?
1✔
215
    has_role?(:submitter, group)
1✔
216
  end
217

218
  # Returns true if the user can admin the group
219
  def can_admin?(group)
1✔
220
    return true if super_admin?
1✔
221
    has_role? :group_admin, group
1✔
222
  end
223

224
  # Returns the list of groups where the user can submit datasets
225
  def submitter_groups
1✔
226
    @submitter_groups = if super_admin?
×
227
                          Group.all.to_a
×
228
                        else
229
                          (Group.with_role(:submitter, self) + Group.with_role(:group_admin, self)).uniq
×
230
                        end
231
  end
232

233
  # Returns the list of groups where the user is an administrator
234
  def admin_groups
1✔
235
    @admin_groups ||= if super_admin?
×
236
                        Group.all.to_a
×
237
                      else
238
                        Group.with_role(:group_admin, self)
×
239
                      end
240
  end
241

242
  def submitter_or_admin_groups
1✔
243
    submitter_groups | admin_groups
×
244
  end
245

246
  def pending_notifications_count
1✔
247
    WorkActivityNotification.where(user_id: id, read_at: nil).count
×
248
  end
249

250
  def assign_default_role
1✔
251
    @just_created = true
1✔
252
    add_role(:submitter, default_group) unless has_role?(:submitter, default_group)
1✔
253
    default_group.enable_messages_for(user: self)
1✔
254
  end
255

256
  # Returns true if the user has notification e-mails enabled
257
  # @return [Boolean]
258
  def email_messages_enabled?
1✔
259
    email_messages_enabled
×
260
  end
261

262
  def safe_uid_check
1✔
263
    self.uid = self.class.safe_uid(uid)
1✔
264
  end
265
end
266
# rubocop:enable Metrics/ClassLength
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