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.



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

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.



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

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



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

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) ⇒ 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
# File 'app/models/user.rb', line 89

def self.new_for_uid(uid)
  user = User.find_by(uid:)
  if user.nil?
    user = User.new(uid:, email: "#{uid}@princeton.edu")
    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



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

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



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

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



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

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



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

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

#assign_default_roleObject



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

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)


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

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)


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

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.



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

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)


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

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).



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

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).



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

def given_name_safe
  given_name.presence || uid
end

#moderator?Boolean

Returns:

  • (Boolean)


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

def moderator?
  admin_groups.count > 0
end

#pending_notifications_countObject



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

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

#safe_uid_checkObject



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

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



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

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



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

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)


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

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