Passed
Push — master ( 670efe...d1e50f )
by Jesus
05:17
created

User.activate()   A

Complexity

Conditions 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 5
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 ::APIConcern
24
  include ::BbbApi
25
26
  attr_accessor :reset_token
27
  after_create :assign_default_role
28
  after_create :initialize_main_room
29
30
  before_save { email.try(:downcase!) }
31
32
  before_destroy :destroy_rooms
33
34
  has_many :rooms
35
  belongs_to :main_room, class_name: 'Room', foreign_key: :room_id, required: false
36
37
  validates :name, length: { maximum: 256 }, presence: true
38
  validates :provider, presence: true
39
  validate :check_if_email_can_be_blank
40
  validates :email, length: { maximum: 256 }, allow_blank: true,
41
                    uniqueness: { case_sensitive: false, scope: :provider },
42
                    format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
43
44
  validates :password, length: { minimum: 6 }, confirmation: true, if: :greenlight_account?, on: :create
45
46
  # Bypass validation if omniauth
47
  validates :accepted_terms, acceptance: true,
48
                             unless: -> { !greenlight_account? || !Rails.configuration.terms }
49
50
  # We don't want to require password validations on all accounts.
51
  has_secure_password(validations: false)
52
53
  class << self
54
    # Generates a user from omniauth.
55
    def from_omniauth(auth)
56
      # Provider is the customer name if in loadbalanced config mode
57
      provider = auth['provider'] == "bn_launcher" ? auth['info']['customer'] : auth['provider']
58
      u = find_by(social_uid: auth['uid'], provider: provider)
59
60
      if ENV["MAINTENANCE_MODE"] == "readonly"
61
        raise ActiveRecord::ReadOnlyRecord if u.nil?
62
63
        return u
64
      end
65
66
      return User.create(
67
        name: auth_name(auth),
68
        username: auth_username(auth),
69
        email: auth_email(auth),
70
        social_uid: auth['uid'],
71
        provider: provider,
72
        image: auth_image(auth),
73
        email_verified: true
74
      ) if u.nil?
75
76
      u.name = auth_name(auth) unless u.name
77
      u.username = auth_username(auth) unless u.username
78
      u.email = auth_email(auth)
79
      u.image = auth_image(auth)
80
      u.email_verified = true
81
      u.save!
82
      u
83
    end
84
85
    private
86
87
    # Provider attributes.
88
    def auth_name(auth)
89
      case auth['provider']
90
      when :office365
91
        auth['info']['display_name']
92
      else
93
        auth['info']['name']
94
      end
95
    end
96
97
    def auth_username(auth)
98
      case auth['provider']
99
      when :google
100
        auth['info']['email'].split('@').first
101
      when :bn_launcher
102
        auth['info']['username']
103
      else
104
        auth['info']['nickname']
105
      end
106
    end
107
108
    def auth_email(auth)
109
      auth['info']['email']
110
    end
111
112
    def auth_image(auth)
113
      case auth['provider']
114
      when :twitter
115
        auth['info']['image'].gsub("http", "https").gsub("_normal", "")
116
      else
117
        auth['info']['image']
118
      end
119
    end
120
  end
121
122
  def self.admins_search(string)
123
    active_database = Rails.configuration.database_configuration[Rails.env]["adapter"]
124
    # Postgres requires created_at to be cast to a string
125
    created_at_query = if active_database == "postgresql"
126
      "created_at::text"
127
    else
128
      "created_at"
129
    end
130
131
    search_query = "users.name LIKE :search OR email LIKE :search OR username LIKE :search" \
132
                   " OR users.#{created_at_query} LIKE :search OR provider LIKE :search"
133
    search_param = "%#{string}%"
134
    where(search_query, search: search_param)
135
  end
136
137
  def self.admins_order(column, direction)
138
    order("#{column} #{direction}")
139
  end
140
141
  def all_recordings(search_params = {}, ret_search_params = false)
142
    pag_num = Rails.configuration.pagination_number
143
144
    pag_loops = rooms.length / pag_num - 1
145
146
    res = { recordings: [] }
147
148
    (0..pag_loops).each do |i|
149
      pag_rooms = rooms[pag_num * i, pag_num]
150
151
      # bbb.get_recordings returns an object
152
      # take only the array portion of the object that is returned
153
      full_res = bbb.get_recordings(meetingID: pag_rooms.pluck(:bbb_id))
154
      res[:recordings].push(*full_res[:recordings])
155
    end
156
157
    last_pag_room = rooms[pag_num * (pag_loops + 1), rooms.length % pag_num]
158
159
    full_res = bbb.get_recordings(meetingID: last_pag_room.pluck(:bbb_id))
160
    res[:recordings].push(*full_res[:recordings])
161
162
    format_recordings(res, search_params, ret_search_params)
163
  end
164
165
  # Activates an account and initialize a users main room
166
  def activate
167
    update_attribute(:email_verified, true)
168
    update_attribute(:activated_at, Time.zone.now)
169
    save
170
  end
171
172
  def activated?
173
    return true unless Rails.configuration.enable_email_verification
174
    email_verified
175
  end
176
177
  # Sets the password reset attributes.
178
  def create_reset_digest
179
    self.reset_token = User.new_token
180
    update_attribute(:reset_digest,  User.digest(reset_token))
181
    update_attribute(:reset_sent_at, Time.zone.now)
182
  end
183
184
  # Returns true if the given token matches the digest.
185
  def authenticated?(attribute, token)
186
    digest = send("#{attribute}_digest")
187
    return false if digest.nil?
188
    BCrypt::Password.new(digest).is_password?(token)
189
  end
190
191
  # Return true if password reset link expires
192
  def password_reset_expired?
193
    reset_sent_at < 2.hours.ago
194
  end
195
196
  # Retrives a list of all a users rooms that are not the main room, sorted by last session date.
197
  def secondary_rooms
198
    secondary = (rooms - [main_room])
199
    no_session, session = secondary.partition { |r| r.last_session.nil? }
200
    sorted = session.sort_by(&:last_session)
201
    sorted + no_session
202
  end
203
204
  def name_chunk
205
    charset = ("a".."z").to_a - %w(b i l o s) + ("2".."9").to_a - %w(5 8)
206
    chunk = name.parameterize[0...3]
207
    if chunk.empty?
208
      chunk + (0...3).map { charset.to_a[rand(charset.size)] }.join
209
    elsif chunk.length == 1
210
      chunk + (0...2).map { charset.to_a[rand(charset.size)] }.join
211
    elsif chunk.length == 2
212
      chunk + (0...1).map { charset.to_a[rand(charset.size)] }.join
213
    else
214
      chunk
215
    end
216
  end
217
218
  def greenlight_account?
219
    return true unless provider # For testing cases when provider is set to null
220
    return true if provider == "greenlight"
221
    return false unless Rails.configuration.loadbalanced_configuration
222
    # Proceed with fetching the provider info
223
    provider_info = retrieve_provider_info(provider, 'api2', 'getUserGreenlightCredentials')
224
    provider_info['provider'] == 'greenlight'
225
  end
226
227
  def activation_token
228
    # Create the token.
229
    create_reset_activation_digest(User.new_token)
230
  end
231
232
  def admin_of?(user)
233
    if Rails.configuration.loadbalanced_configuration
234
      if has_role? :super_admin
235
        id != user.id
236
      else
237
        (has_role? :admin) && (id != user.id) && (provider == user.provider) && (!user.has_role? :super_admin)
238
      end
239
    else
240
      ((has_role? :admin) || (has_role? :super_admin)) && (id != user.id)
241
    end
242
  end
243
244
  def self.digest(string)
245
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
246
    BCrypt::Password.create(string, cost: cost)
247
  end
248
249
  # Returns a random token.
250
  def self.new_token
251
    SecureRandom.urlsafe_base64
252
  end
253
254
  private
255
256
  def create_reset_activation_digest(token)
257
    # Create the digest and persist it.
258
    self.activation_digest = User.digest(token)
259
    save
260
    token
261
  end
262
263
  # Destory a users rooms when they are removed.
264
  def destroy_rooms
265
    rooms.destroy_all
266
  end
267
268
  # Initializes a room for the user and assign a BigBlueButton user id.
269
  def initialize_main_room
270
    self.uid = "gl-#{(0...12).map { rand(65..90).chr }.join.downcase}"
271
    self.main_room = Room.create!(owner: self, name: I18n.t("home_room"))
272
    save
273
  end
274
275
  # Initialize the user to use the default user role
276
  def assign_default_role
277
    add_role(:user) if roles.blank?
278
  end
279
280
  def check_if_email_can_be_blank
281
    if email.blank?
282
      if Rails.configuration.loadbalanced_configuration && greenlight_account?
283
        errors.add(:email, I18n.t("errors.messages.blank"))
284
      elsif provider == "greenlight"
285
        errors.add(:email, I18n.t("errors.messages.blank"))
286
      end
287
    end
288
  end
289
end
290