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

pulibrary / pdc_describe / bcfc06e8-a5d8-4369-a72f-de9ecf1ada29

pending completion
bcfc06e8-a5d8-4369-a72f-de9ecf1ada29

Pull #963

circleci

mccalluc
cursor css
Pull Request #963: Add row deletion and reordering to irb tables

1622 of 1848 relevant lines covered (87.77%)

66.84 hits per line

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

54.48
/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
  # CollectionOptions model extensible options set for Collections and Users
13
  has_many :collection_options, dependent: :destroy
1✔
14
  has_many :collection_messaging_options, -> { where(option_type: CollectionOption::EMAIL_MESSAGES) }, class_name: "CollectionOption", dependent: :destroy
421✔
15

16
  has_many :collections_with_options, through: :collection_options, source: :collection
1✔
17
  has_many :collections_with_messaging, through: :collection_messaging_options, source: :collection
1✔
18

19
  after_create :assign_default_role
1✔
20

21
  attr_accessor :just_created
1✔
22

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

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

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

54
  # Updates an existing User record with some information from CAS. This is useful
55
  # for records created before the user ever logged in (e.g. to gran them permissions
56
  # to collections).
57
  def update_with_cas(access_token)
1✔
58
    self.provider = access_token.provider
×
59
    self.email = access_token.extra.mail
×
60
    self.display_name = access_token.extra.givenname || access_token.uid # Harriet
×
61
    self.family_name = access_token.extra.sn || access_token.uid # Tubman
×
62
    self.full_name = access_token.extra.displayname || access_token.uid # "Harriet Tubman"
×
63
    self.default_collection_id = Collection.default_for_department(access_token.extra.departmentnumber)&.id
×
64
    save!
×
65
  end
66

67
  # Creates a new user by uid. If the user already exists it returns the existing user.
68
  def self.new_for_uid(uid)
1✔
69
    user = User.find_by(uid: uid)
36✔
70
    if user.nil?
36✔
71
      user = User.new(uid: uid, email: "#{uid}@princeton.edu")
16✔
72
      user.save!
16✔
73
    end
74
    user
36✔
75
  end
76

77
  def self.new_super_admin(uid)
1✔
78
    user = new_for_uid(uid)
16✔
79
    user.add_role(:super_admin) unless user.has_role?(:super_admin)
16✔
80
    user.add_role(:collection_admin) unless user.has_role?(:collection_admin)
16✔
81
    user
16✔
82
  end
83

84
  # rubocop:disable Metrics/MethodLength
85
  def self.new_from_csv_params(csv_params)
1✔
86
    email = "#{csv_params['Net ID']}@princeton.edu"
×
87
    uid = csv_params["Net ID"]
×
88
    full_name = "#{csv_params['First Name']} #{csv_params['Last Name']}"
×
89
    display_name = csv_params["First Name"]
×
90
    orcid = csv_params["ORCID ID"]
×
91
    user = User.where(email: email).first_or_create
×
92
    params_hash = {
93
      email: email,
×
94
      uid: uid,
95
      orcid: orcid,
96
      full_name: (full_name if user.full_name.blank?),
×
97
      display_name: (display_name if user.display_name.blank?)
×
98
    }.compact
99

100
    user.update(params_hash)
×
101
    Rails.logger.info "Successfully created or updated #{user.email}"
×
102
    user
×
103
  end
104
  # rubocop:enable Metrics/MethodLength
105

106
  def self.create_users_from_csv(csv)
1✔
107
    users = []
×
108
    CSV.foreach(csv, headers: true) do |row|
×
109
      next if row["Net ID"] == "N/A"
×
110
      users << new_from_csv_params(row.to_hash)
×
111
    end
112
    users
×
113
  end
114

115
  # Creates the default users as indicated in the super_admin config file
116
  # and the default administrators and submitters for each collection.
117
  # It only creates missing records, i.e. if the records already exist it
118
  # will not create a duplicate. It also does _not_ remove already configured
119
  # access to other collections.
120
  def self.create_default_users
1✔
121
    update_super_admins
×
122

123
    Collection.find_each do |collection|
×
124
      Rails.logger.info "Setting up admins for collection #{collection.title}"
×
125
      collection.default_admins_list.each do |uid|
×
126
        user = User.new_for_uid(uid)
×
127
        user.add_role :collection_admin, collection
×
128
      end
129

130
      Rails.logger.info "Setting up submitters for collection #{collection.title}"
×
131
      collection.default_submitters_list.each do |uid|
×
132
        user = User.new_for_uid(uid)
×
133
        user.add_role :submitter, collection
×
134
      end
135
    end
136
  end
137

138
  def self.update_super_admins
1✔
139
    Rails.logger.info "Setting super administrators"
×
140
    Rails.configuration.super_admins.each do |uid|
×
141
      new_super_admin(uid)
×
142
    end
143
  end
144

145
  # Returns a string with the UID (netid) for all the users.
146
  # We use this string to power the JavaScript @mention functionality when adding messages to works.
147
  def self.all_uids_string
1✔
148
    User.all.map { |user| '"' + user.uid + '"' }.join(", ")
36✔
149
  end
150

151
  ##
152
  # Is this user a super_admin? super_admins automatically get admin status in every
153
  # collection, and they can make new collections.
154
  # @return [Boolean]
155
  def super_admin?
1✔
156
    has_role? :super_admin
621✔
157
  rescue => ex
158
    Rails.logger.error("Unexpected error checking super_admin: #{ex}")
×
159
    false
×
160
  end
161

162
  # Returns a display name that always has a value
163
  # This is needed because we have records in the Users table that are created automatically
164
  # in which the only value we have for sure its their uid (aka NetID).
165
  def display_name_safe
1✔
166
    display_name.presence || uid
92✔
167
  end
168

169
  def moderator?
1✔
170
    admin_collections.count > 0
123✔
171
  end
172

173
  # Returns a reference to the user's default collection.
174
  def default_collection
1✔
175
    if default_collection_id.nil?
655✔
176
      Collection.default
444✔
177
    else
178
      Collection.find(default_collection_id)
211✔
179
    end
180
  end
181

182
  # True if the user can submit datasets to the collection
183
  def can_submit?(collection)
1✔
184
    return true if super_admin?
210✔
185
    has_role?(:submitter, collection)
210✔
186
  end
187

188
  # Returns true if the user can admin the collection
189
  def can_admin?(collection)
1✔
190
    return true if super_admin?
253✔
191
    has_role? :collection_admin, collection
244✔
192
  end
193

194
  # Returns the list of collections where the user can submit datasets
195
  def submitter_collections
1✔
196
    @submitter_collections = if super_admin?
17✔
197
                               Collection.all.to_a
1✔
198
                             else
199
                               Collection.with_role(:submitter, self)
16✔
200
                             end
201
  end
202

203
  # Returns the list of collections where the user is an administrator
204
  def admin_collections
1✔
205
    @admin_collections ||= if super_admin?
213✔
206
                             Collection.all.to_a
4✔
207
                           else
208
                             Collection.with_role(:collection_admin, self)
101✔
209
                           end
210
  end
211

212
  def submitter_or_admin_collections
1✔
213
    submitter_collections | admin_collections
×
214
  end
215

216
  def pending_notifications_count
1✔
217
    WorkActivityNotification.where(user_id: id, read_at: nil).count
31✔
218
  end
219

220
  def assign_default_role
1✔
221
    @just_created = true
210✔
222
    add_role(:submitter, default_collection) unless has_role?(:submitter, default_collection)
210✔
223
    enable_messages_from(collection: default_collection)
210✔
224
  end
225

226
  # Returns true if the user has notification e-mails enabled
227
  # @return [Boolean]
228
  def email_messages_enabled?
1✔
229
    email_messages_enabled
49✔
230
  end
231

232
  # Permit this user to receive notification messages for members of a given Collection
233
  # @param collection [Collection]
234
  def enable_messages_from(collection:)
1✔
235
    raise(ArgumentError, "User #{uid} is not an administrator or depositor for the collection #{collection.title}") unless can_admin?(collection) || can_submit?(collection)
210✔
236
    collection_messaging_options << CollectionOption.new(option_type: CollectionOption::EMAIL_MESSAGES, user: self, collection: collection)
210✔
237
  end
238

239
  # Disable this user from receiving notification messages for members of a given Collection
240
  # @param collection [Collection]
241
  def disable_messages_from(collection:)
1✔
242
    raise(ArgumentError, "User #{uid} is not an administrator or depositor for the collection #{collection.title}") unless can_admin?(collection) || can_submit?(collection)
×
243
    collections_with_messaging.destroy(collection)
×
244
  end
245

246
  # Returns true if the user has notification e-mails enabled for a given collection
247
  # @param collection [Collection]
248
  # @return [Boolean]
249
  def messages_enabled_from?(collection:)
1✔
250
    found = collection_messaging_options.find_by(collection: collection)
×
251

252
    !found.nil?
×
253
  end
254
end
255
# 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