Passed
Push — master ( beadd4...2775b1 )
by Jesus
05:37 queued 11s
created

User.assign_default_role()   A

Complexity

Conditions 2

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
dl 0
loc 3
rs 10
1
# frozen_string_literal: true
2
3
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
4
#
5
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
6
#
7
# This program is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU Lesser General Public License as published by the Free Software
9
# Foundation; either version 3.0 of the License, or (at your option) any later
10
# version.
11
#
12
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
15
#
16
# You should have received a copy of the GNU Lesser General Public License along
17
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
18
19
require 'bbb_api'
20
21
class User < ApplicationRecord
22
  rolify
23
  include ::BbbApi
24
25
  attr_accessor :reset_token
26
  after_create :assign_default_role
27
  after_create :initialize_main_room
28
29
  before_save { email.try(:downcase!) }
30
31
  before_destroy :destroy_rooms
32
33
  has_many :rooms
34
  belongs_to :main_room, class_name: 'Room', foreign_key: :room_id, required: false
35
36
  validates :name, length: { maximum: 256 }, presence: true
37
  validates :provider, presence: true
38
  validate :check_if_email_can_be_blank
39
  validates :email, length: { maximum: 256 }, allow_blank: true,
40
                    uniqueness: { case_sensitive: false, scope: :provider },
41
                    format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
42
43
  validates :password, length: { minimum: 6 }, confirmation: true, if: :greenlight_account?, on: :create
44
45
  # Bypass validation if omniauth
46
  validates :accepted_terms, acceptance: true,
47
                             unless: -> { !greenlight_account? || !Rails.configuration.terms }
48
49
  # We don't want to require password validations on all accounts.
50
  has_secure_password(validations: false)
51
52
  class << self
53
    # Generates a user from omniauth.
54
    def from_omniauth(auth)
55
      # Provider is the customer name if in loadbalanced config mode
56
      provider = auth['provider'] == "bn_launcher" ? auth['info']['customer'] : auth['provider']
57
      find_or_initialize_by(social_uid: auth['uid'], provider: provider).tap do |u|
58
        u.name = auth_name(auth) unless u.name
59
        u.username = auth_username(auth) unless u.username
60
        u.email = auth_email(auth)
61
        u.image = auth_image(auth)
62
        u.email_verified = true
63
        u.save!
64
      end
65
    end
66
67
    private
68
69
    # Provider attributes.
70
    def auth_name(auth)
71
      case auth['provider']
72
      when :office365
73
        auth['info']['display_name']
74
      else
75
        auth['info']['name']
76
      end
77
    end
78
79
    def auth_username(auth)
80
      case auth['provider']
81
      when :google
82
        auth['info']['email'].split('@').first
83
      when :bn_launcher
84
        auth['info']['username']
85
      else
86
        auth['info']['nickname']
87
      end
88
    end
89
90
    def auth_email(auth)
91
      auth['info']['email']
92
    end
93
94
    def auth_image(auth)
95
      case auth['provider']
96
      when :twitter
97
        auth['info']['image'].gsub("http", "https").gsub("_normal", "")
98
      else
99
        auth['info']['image']
100
      end
101
    end
102
  end
103
104
  def self.admins_search(string, role)
105
    active_database = Rails.configuration.database_configuration[Rails.env]["adapter"]
106
    # Postgres requires created_at to be cast to a string
107
    created_at_query = if active_database == "postgresql"
108
      "created_at::text"
109
    else
110
      "created_at"
111
    end
112
113
    search_query = ""
114
    role_search_param = ""
115
    if role.present?
116
      search_query = "(users.name LIKE :search OR email LIKE :search OR username LIKE :search" \
117
                    " OR users.#{created_at_query} LIKE :search OR provider LIKE :search)" \
118
                    " AND roles.name = :roles_search"
119
      role_search_param = role
120
    else
121
      search_query = "users.name LIKE :search OR email LIKE :search OR username LIKE :search" \
122
                    " OR users.#{created_at_query} LIKE :search OR provider LIKE :search" \
123
                    " OR roles.name LIKE :roles_search"
124
      role_search_param = "%#{string}%".downcase
125
    end
126
127
    search_param = "%#{string}%"
128
    joins("LEFT OUTER JOIN users_roles ON users_roles.user_id = users.id LEFT OUTER JOIN roles " \
129
      "ON roles.id = users_roles.role_id").distinct
130
      .where(search_query, search: search_param, roles_search: role_search_param)
131
  end
132
133
  def self.admins_order(column, direction)
134
    # Arel.sql to avoid sql injection
135
    order(Arel.sql("#{column} #{direction}"))
136
  end
137
138
  # Activates an account and initialize a users main room
139
  def activate
140
    update_attribute(:email_verified, true)
141
    update_attribute(:activated_at, Time.zone.now)
142
    save
143
  end
144
145
  def activated?
146
    return true unless Rails.configuration.enable_email_verification
147
    email_verified
148
  end
149
150
  # Sets the password reset attributes.
151
  def create_reset_digest
152
    self.reset_token = User.new_token
153
    update_attribute(:reset_digest,  User.digest(reset_token))
154
    update_attribute(:reset_sent_at, Time.zone.now)
155
  end
156
157
  # Returns true if the given token matches the digest.
158
  def authenticated?(attribute, token)
159
    digest = send("#{attribute}_digest")
160
    return false if digest.nil?
161
    BCrypt::Password.new(digest).is_password?(token)
162
  end
163
164
  # Return true if password reset link expires
165
  def password_reset_expired?
166
    reset_sent_at < 2.hours.ago
167
  end
168
169
  # Retrives a list of all a users rooms that are not the main room, sorted by last session date.
170
  def secondary_rooms
171
    secondary = (rooms - [main_room])
172
    no_session, session = secondary.partition { |r| r.last_session.nil? }
173
    sorted = session.sort_by(&:last_session)
174
    sorted + no_session
175
  end
176
177
  def name_chunk
178
    charset = ("a".."z").to_a - %w(b i l o s) + ("2".."9").to_a - %w(5 8)
179
    chunk = name.parameterize[0...3]
180
    if chunk.empty?
181
      chunk + (0...3).map { charset.to_a[rand(charset.size)] }.join
182
    elsif chunk.length == 1
183
      chunk + (0...2).map { charset.to_a[rand(charset.size)] }.join
184
    elsif chunk.length == 2
185
      chunk + (0...1).map { charset.to_a[rand(charset.size)] }.join
186
    else
187
      chunk
188
    end
189
  end
190
191
  def greenlight_account?
192
    return true unless provider # For testing cases when provider is set to null
193
    return true if provider == "greenlight"
194
    return false unless Rails.configuration.loadbalanced_configuration
195
    # Proceed with fetching the provider info
196
    provider_info = retrieve_provider_info(provider, 'api2', 'getUserGreenlightCredentials')
197
    provider_info['provider'] == 'greenlight'
198
  end
199
200
  def activation_token
201
    # Create the token.
202
    create_reset_activation_digest(User.new_token)
203
  end
204
205
  def admin_of?(user)
206
    if Rails.configuration.loadbalanced_configuration
207
      # Pulls in the user roles if they weren't request in the original request
208
      # So the has_cached_role? doesn't always return false
209
      user.roles
210
      if has_cached_role? :super_admin
211
        id != user.id
212
      else
213
        (has_cached_role? :admin) && (id != user.id) && (provider == user.provider) &&
214
          (!user.has_cached_role? :super_admin)
215
      end
216
    else
217
      ((has_cached_role? :admin) || (has_cached_role? :super_admin)) && (id != user.id)
218
    end
219
  end
220
221
  def self.digest(string)
222
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
223
    BCrypt::Password.create(string, cost: cost)
224
  end
225
226
  # Returns a random token.
227
  def self.new_token
228
    SecureRandom.urlsafe_base64
229
  end
230
231
  private
232
233
  def create_reset_activation_digest(token)
234
    # Create the digest and persist it.
235
    self.activation_digest = User.digest(token)
236
    save
237
    token
238
  end
239
240
  # Destory a users rooms when they are removed.
241
  def destroy_rooms
242
    rooms.destroy_all
243
  end
244
245
  # Initializes a room for the user and assign a BigBlueButton user id.
246
  def initialize_main_room
247
    self.uid = "gl-#{(0...12).map { rand(65..90).chr }.join.downcase}"
248
    self.main_room = Room.create!(owner: self, name: I18n.t("home_room"))
249
    save
250
  end
251
252
  # Initialize the user to use the default user role
253
  def assign_default_role
254
    add_role(:user) if roles.blank?
255
  end
256
257
  def check_if_email_can_be_blank
258
    if email.blank?
259
      if Rails.configuration.loadbalanced_configuration && greenlight_account?
260
        errors.add(:email, I18n.t("errors.messages.blank"))
261
      elsif provider == "greenlight"
262
        errors.add(:email, I18n.t("errors.messages.blank"))
263
      end
264
    end
265
  end
266
end
267