Class: User

Inherits:
ApplicationRecord show all
Extended by:
FriendlyId
Defined in:
app/models/user.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#just_createdObject

Returns the value of attribute just_created.



23
24
25
# File 'app/models/user.rb', line 23

def just_created
  @just_created
end

Class Method Details

.all_uids_stringObject

Returns a string with the UID (netid) for all the users. We use this string to power the JavaScript @mention functionality when adding messages to works.



171
172
173
# File 'app/models/user.rb', line 171

def self.all_uids_string
  User.all.map { |user| '"' + user.uid + '"' }.join(", ")
end

.create_default_usersObject

Creates the default users as indicated in the super_admin config file and the default administrators and submitters for each group. It only creates missing records, i.e. if the records already exist it will not create a duplicate. It also does not remove already configured access to other groups.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'app/models/user.rb', line 144

def self.create_default_users
  update_super_admins

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

    Rails.logger.info "Setting up submitters for group #{group.title}"
    group.default_submitters_list.each do |uid|
      user = User.new_for_uid(uid)
      user.add_role :submitter, group
    end
  end
end

.create_users_from_csv(csv) ⇒ Object

rubocop:enable Metrics/MethodLength



130
131
132
133
134
135
136
137
# File 'app/models/user.rb', line 130

def self.create_users_from_csv(csv)
  users = []
  CSV.foreach(csv, headers: true) do |row|
    next if row["Net ID"] == "N/A"
    users << new_from_csv_params(row.to_hash)
  end
  users
end

.email_from_access_token(access_token) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'app/models/user.rb', line 61

def self.email_from_access_token(access_token)
  if !access_token.extra.mail.nil?
    # For typical Princeton accounts the email comes on the `email` field
    access_token.extra.mail
  elsif User.looks_like_email_address?(access_token.extra.givenname)
    # For Guest Access Accounts (GAP) the email comes in the `givenname`
    access_token.extra.givenname
  end
end

.from_cas(access_token) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'app/models/user.rb', line 32

def self.from_cas(access_token)
  user = User.find_by(uid: safe_uid(access_token.uid))
  if user.nil?
    user = new_from_cas(access_token)
  elsif user.provider.blank?
    user.update_with_cas(access_token)
  end
  user
end

.looks_like_email_address?(value) ⇒ Boolean

Returns:

  • (Boolean)


71
72
73
# File 'app/models/user.rb', line 71

def self.looks_like_email_address?(value)
  URI::MailTo::EMAIL_REGEXP.match?(value)
end

.new_for_uid(uid, default_group_id = nil) ⇒ Object

Creates a new user by uid. If the user already exists it returns the existing user.



89
90
91
92
93
94
95
96
97
# File 'app/models/user.rb', line 89

def self.new_for_uid(uid, default_group_id = nil)
  user = User.find_by(uid:)
  if user.nil?
    user = User.new(uid:, email: "#{uid}@princeton.edu")
    user.default_group_id = default_group_id
    user.save!
  end
  user
end

.new_from_cas(access_token) ⇒ Object

Create a new user with some basic information from CAS.



43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/models/user.rb', line 43

def self.new_from_cas(access_token)
  user = User.new
  user.provider = access_token.provider
  user.uid = safe_uid(access_token.uid) # this is the netid
  user.email = User.email_from_access_token(access_token)
  user.given_name = access_token.extra.givenname || access_token.uid # Harriet
  user.family_name = access_token.extra.sn || access_token.uid # Tubman
  user.full_name = access_token.extra.displayname || access_token.uid # "Harriet Tubman"
  user.default_group_id = Group.default_for_department(access_token.extra.departmentnumber)&.id
  user.save!
  user
end

.new_from_csv_params(csv_params) ⇒ Object

rubocop:disable Metrics/MethodLength



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'app/models/user.rb', line 107

def self.new_from_csv_params(csv_params)
  email = "#{csv_params['Net ID']}@princeton.edu"
  uid = csv_params["Net ID"]
  given_name = csv_params["First Name"]
  family_name = csv_params["Last Name"]
  full_name = "#{given_name} #{family_name}"
  orcid = csv_params["ORCID ID"]
  user = User.where(email:).first_or_create
  params_hash = {
    email:,
    uid:,
    orcid:,
    full_name: (full_name if user.full_name.blank?),
    family_name: (family_name if user.family_name.blank?),
    given_name: (given_name if user.given_name.blank?)
  }.compact

  user.update(params_hash)
  Rails.logger.info "Successfully created or updated #{user.email}"
  user
end

.new_super_admin(uid) ⇒ Object



99
100
101
102
103
104
# File 'app/models/user.rb', line 99

def self.new_super_admin(uid)
  user = new_for_uid(uid)
  user.add_role(:super_admin) unless user.has_role?(:super_admin)
  user.add_role(:group_admin) unless user.has_role?(:group_admin)
  user
end

.safe_uid(uid) ⇒ Object



56
57
58
59
# File 'app/models/user.rb', line 56

def self.safe_uid(uid)
  return uid if uid.blank?
  uid.gsub(/[^(0-9a-zA-Z_\-)]/, "_")
end

.update_super_adminsObject



162
163
164
165
166
167
# File 'app/models/user.rb', line 162

def self.update_super_admins
  Rails.logger.info "Setting super administrators"
  Rails.configuration.super_admins.each do |uid|
    new_super_admin(uid)
  end
end

Instance Method Details

#admin_groupsObject

Returns the list of groups where the user is an administrator



235
236
237
238
239
240
241
# File 'app/models/user.rb', line 235

def admin_groups
  @admin_groups ||= if super_admin?
                      Group.all.to_a
                    else
                      Group.with_role(:group_admin, self)
                    end
end

#assign_default_roleObject



251
252
253
254
255
# File 'app/models/user.rb', line 251

def assign_default_role
  @just_created = true
  add_role(:submitter, default_group) unless has_role?(:submitter, default_group)
  default_group.enable_messages_for(user: self)
end

#can_admin?(group) ⇒ Boolean

Returns true if the user can admin the group

Returns:

  • (Boolean)


220
221
222
223
# File 'app/models/user.rb', line 220

def can_admin?(group)
  return true if super_admin?
  has_role?(:group_admin, group)
end

#can_submit?(group) ⇒ Boolean

True if the user can submit datasets to the group

Returns:

  • (Boolean)


214
215
216
217
# File 'app/models/user.rb', line 214

def can_submit?(group)
  return true if super_admin?
  has_role?(:submitter, group)
end

#default_groupObject

Returns a reference to the user’s default group.



205
206
207
208
209
210
211
# File 'app/models/user.rb', line 205

def default_group
  if default_group_id.nil?
    Group.default
  else
    Group.find(default_group_id)
  end
end

#email_messages_enabled?Boolean

Returns true if the user has notification e-mails enabled

Returns:

  • (Boolean)


259
260
261
# File 'app/models/user.rb', line 259

def email_messages_enabled?
  email_messages_enabled
end

#full_name_safeObject

Returns a full name that always has a value This is needed because we have records in the Users table that are created automatically in which the only value we have for sure its their uid (aka NetID).



196
197
198
# File 'app/models/user.rb', line 196

def full_name_safe
  full_name&.strip.presence || uid
end

#given_name_safeObject

Returns a display name that always has a value This is needed because we have records in the Users table that are created automatically in which the only value we have for sure its their uid (aka NetID).



189
190
191
# File 'app/models/user.rb', line 189

def given_name_safe
  given_name.presence || uid
end

#moderator?Boolean

Returns:

  • (Boolean)


200
201
202
# File 'app/models/user.rb', line 200

def moderator?
  admin_groups.count > 0
end

#pending_notifications_countObject



247
248
249
# File 'app/models/user.rb', line 247

def pending_notifications_count
  WorkActivityNotification.where(user_id: id, read_at: nil).count
end

#safe_uid_checkObject



263
264
265
# File 'app/models/user.rb', line 263

def safe_uid_check
  self.uid = self.class.safe_uid(uid)
end

#submitter_groupsObject

Returns the list of groups where the user can submit datasets



226
227
228
229
230
231
232
# File 'app/models/user.rb', line 226

def submitter_groups
  @submitter_groups = if super_admin?
                        Group.all.to_a
                      else
                        (Group.with_role(:submitter, self) + Group.with_role(:group_admin, self)).uniq
                      end
end

#submitter_or_admin_groupsObject



243
244
245
# File 'app/models/user.rb', line 243

def submitter_or_admin_groups
  submitter_groups | admin_groups
end

#super_admin?Boolean

Is this user a super_admin? super_admins automatically get admin status in every group, and they can make new groups.

Returns:

  • (Boolean)


179
180
181
182
183
184
# File 'app/models/user.rb', line 179

def super_admin?
  has_role? :super_admin
rescue => ex
  Rails.logger.error("Unexpected error checking super_admin: #{ex}")
  false
end

#update_with_cas(access_token) ⇒ Object

Updates an existing User record with some information from CAS. This is useful for records created before the user ever logged in (e.g. to grant them permissions to groups).



78
79
80
81
82
83
84
85
86
# File 'app/models/user.rb', line 78

def update_with_cas(access_token)
  self.provider = access_token.provider
  self.email = User.email_from_access_token(access_token)
  self.given_name = access_token.extra.givenname || access_token.uid # Harriet
  self.family_name = access_token.extra.sn || access_token.uid # Tubman
  self.full_name = access_token.extra.displayname || access_token.uid # "Harriet Tubman"
  self.default_group_id ||= Group.default_for_department(access_token.extra.departmentnumber)&.id
  save!
end