Passed
Push — master ( 02b342...4fc171 )
by Jesus
04:50
created

UsersController   F

Complexity

Total Complexity 72

Size/Duplication

Total Lines 303
Duplicated Lines 5.28 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 16
loc 303
rs 2.64
wmc 72

8 Methods

Rating   Name   Duplication   Size   Complexity  
A ldap_signin() 0 2 1
B signin() 4 18 8
A valid_user_or_captcha() 0 6 2
A send_registration_email() 0 12 4
B update_roles() 0 59 3
A find_user() 0 3 1
A passes_invite_reqs() 0 8 2
A send_verification() 0 11 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like UsersController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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
class UsersController < ApplicationController
20
  include RecordingsHelper
21
  include Pagy::Backend
22
  include Emailer
23
  include Registrar
24
  include Recorder
25
26
  before_action :find_user, only: [:edit, :update, :destroy]
27
  before_action :ensure_unauthenticated, only: [:new, :create, :signin]
28
29
  # POST /u
30
  def create
31
    # Verify that GreenLight is configured to allow user signup.
32
    return unless Rails.configuration.allow_user_signup
33
34
    @user = User.new(user_params)
35
    @user.provider = @user_domain
36
37
    # User or recpatcha is not valid
38
    render(:new) && return unless valid_user_or_captcha
39
40
    # Redirect to root if user token is either invalid or expired
41 View Code Duplication
    return redirect_to root_path, flash: { alert: I18n.t("registration.invite.fail") } unless passes_invite_reqs
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
42
43
    # User has passed all validations required
44
    @user.save
45
46
    # Set user to pending and redirect if Approval Registration is set
47 View Code Duplication
    if approval_registration
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
48
      @user.add_role :pending
49
50
      return redirect_to root_path,
51
        flash: { success: I18n.t("registration.approval.signup") } unless Rails.configuration.enable_email_verification
52
    end
53
54
    send_registration_email if Rails.configuration.enable_email_verification
55
56
    # Sign in automatically if email verification is disabled or if user is already verified.
57
    login(@user) && return if !Rails.configuration.enable_email_verification || @user.email_verified
58
59
    send_verification
60
61
    redirect_to root_path
62
  end
63
64
  # GET /signin
65
  def signin
66 View Code Duplication
    unless params[:old_twitter_user_id].nil? && session[:old_twitter_user_id].nil?
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
67
      flash[:alert] = I18n.t("registration.deprecated.new_signin")
68
      session[:old_twitter_user_id] = params[:old_twitter_user_id] unless params[:old_twitter_user_id].nil?
69
    end
70
71
    providers = configured_providers
72
    if (!allow_user_signup? || !allow_greenlight_accounts?) && providers.count == 1 &&
73
       !Rails.configuration.loadbalanced_configuration
74
      provider_path = if Rails.configuration.omniauth_ldap
75
        ldap_signin_path
76
      else
77
        "#{Rails.configuration.relative_url_root}/auth/#{providers.first}"
78
      end
79
80
      return redirect_to provider_path
81
    end
82
  end
83
84
  # GET /ldap_signin
85
  def ldap_signin
86
  end
87
88
  # GET /signup
89
  def new
90
    return redirect_to root_path unless Rails.configuration.allow_user_signup
91
92
    # Check if the user needs to be invited
93
    if invite_registration
94
      redirect_to root_path, flash: { alert: I18n.t("registration.invite.no_invite") } unless params[:invite_token]
95
96
      session[:invite_token] = params[:invite_token]
97
    end
98
99 View Code Duplication
    unless params[:old_twitter_user_id].nil? && session[:old_twitter_user_id].nil?
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
100
      logout
101
      flash.now[:alert] = I18n.t("registration.deprecated.new_signin")
102
      session[:old_twitter_user_id] = params[:old_twitter_user_id] unless params[:old_twitter_user_id].nil?
103
    end
104
105
    @user = User.new
106
  end
107
108
  # GET /u/:user_uid/edit
109
  def edit
110
    if current_user
111
      redirect_to current_user.main_room if @user != current_user && !current_user.admin_of?(@user)
112
    else
113
      redirect_to root_path
114
    end
115
  end
116
117
  # PATCH /u/:user_uid/edit
118
  def update
119
    redirect_path = current_user.admin_of?(@user) ? admins_path : edit_user_path(@user)
120
121
    if params[:setting] == "password"
122
      # Update the users password.
123
      errors = {}
124
125
      if @user.authenticate(user_params[:password])
126
        # Verify that the new passwords match.
127
        if user_params[:new_password] == user_params[:password_confirmation]
128
          @user.password = user_params[:new_password]
129
        else
130
          # New passwords don't match.
131
          errors[:password_confirmation] = "doesn't match"
132
        end
133
      else
134
        # Original password is incorrect, can't update.
135
        errors[:password] = "is incorrect"
136
      end
137
138
      if errors.empty? && @user.save
139
        # Notify the user that their account has been updated.
140
        flash[:success] = I18n.t("info_update_success")
141
        redirect_to redirect_path
142
      else
143
        # Append custom errors.
144
        errors.each { |k, v| @user.errors.add(k, v) }
145
        render :edit, params: { settings: params[:settings] }
146
      end
147
    elsif user_params[:email] != @user.email && @user.update_attributes(user_params) && update_roles
148
      @user.update_attributes(email_verified: false)
149
150
      flash[:success] = I18n.t("info_update_success")
151
      redirect_to redirect_path
152
    elsif @user.update_attributes(user_params) && update_roles
153
      update_locale(@user)
154
155
      flash[:success] = I18n.t("info_update_success")
156
      redirect_to redirect_path
157
    else
158
      render :edit, params: { settings: params[:settings] }
159
    end
160
  end
161
162
  # DELETE /u/:user_uid
163
  def destroy
164
    if current_user && current_user == @user
165
      @user.destroy
166
      session.delete(:user_id)
167
    elsif current_user.admin_of?(@user)
168
      begin
169
        @user.destroy
170
      rescue => e
171
        logger.error "Error in user deletion: #{e}"
172
        flash[:alert] = I18n.t(params[:message], default: I18n.t("administrator.flash.delete_fail"))
173
      else
174
        flash[:success] = I18n.t("administrator.flash.delete")
175
      end
176
      redirect_to(admins_path) && return
177
    end
178
    redirect_to root_path
179
  end
180
181
  # GET /u/:user_uid/recordings
182
  def recordings
183
    if current_user && current_user.uid == params[:user_uid]
184
      @search, @order_column, @order_direction, recs =
185
        all_recordings(current_user.rooms.pluck(:bbb_id), current_user.provider,
186
         params.permit(:search, :column, :direction), true)
187
      @pagy, @recordings = pagy_array(recs)
188
    else
189
      redirect_to root_path
190
    end
191
  end
192
193
  # GET | POST /terms
194
  def terms
195
    redirect_to '/404' unless Rails.configuration.terms
196
197
    if params[:accept] == "true"
198
      current_user.update_attributes(accepted_terms: true)
199
      login(current_user)
200
    end
201
  end
202
203
  private
204
205
  def find_user
206
    @user = User.where(uid: params[:user_uid]).includes(:roles).first
207
  end
208
209
  def ensure_unauthenticated
210
    redirect_to current_user.main_room if current_user && params[:old_twitter_user_id].nil?
211
  end
212
213
  def user_params
214
    params.require(:user).permit(:name, :email, :image, :password, :password_confirmation,
215
      :new_password, :provider, :accepted_terms, :language)
216
  end
217
218
  def send_verification
219
    # Start email verification and redirect to root.
220
    begin
221
      send_activation_email(@user)
222
    rescue => e
223
      logger.error "Error in email delivery: #{e}"
224
      flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error"))
225
    else
226
      flash[:success] = I18n.t("email_sent", email_type: t("verify.verification"))
227
    end
228
  end
229
230
  def send_registration_email
231
    begin
232
      if invite_registration
233
        send_invite_user_signup_email(@user)
234
      elsif approval_registration
235
        send_approval_user_signup_email(@user)
236
      end
237
    rescue => e
238
      logger.error "Error in email delivery: #{e}"
239
      flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error"))
240
    end
241
  end
242
243
  # Add validation errors to model if they exist
244
  def valid_user_or_captcha
245
    valid_user = @user.valid?
246
    valid_captcha = Rails.configuration.recaptcha_enabled ? verify_recaptcha(model: @user) : true
247
248
    valid_user && valid_captcha
249
  end
250
251
  # Checks if the user passes the requirements to be invited
252
  def passes_invite_reqs
253
    # check if user needs to be invited and IS invited
254
    invitation = check_user_invited(@user.email, session[:invite_token], @user_domain)
255
256
    @user.email_verified = true if invitation[:verified]
257
258
    invitation[:present]
259
  end
260
261
  # Updates as user's roles
262
  def update_roles
263
    # Check that the user can edit roles
264
    if current_user.highest_priority_role.can_edit_roles
265
      new_roles = params[:user][:role_ids].split(' ').map(&:to_i)
266
      old_roles = @user.roles.pluck(:id)
267
268
      added_role_ids = new_roles - old_roles
269
      removed_role_ids = old_roles - new_roles
270
271
      added_roles = []
272
      removed_roles = []
273
      current_user_role = current_user.highest_priority_role
274
275
      # Check that the user has the permissions to add all the new roles
276
      added_role_ids.each do |id|
277
        role = Role.find(id)
278
279
        # Admins are able to add the admin role to other users. All other roles may only
280
        # add roles with a higher priority
281
        if (role.priority > current_user_role.priority || current_user_role.name == "admin") &&
282
           role.provider == @user_domain
283
          added_roles << role
284
        else
285
          flash[:alert] = I18n.t("administrator.roles.invalid_assignment")
286
          return false
287
        end
288
      end
289
290
      # Check that the user has the permissions to remove all the deleted roles
291
      removed_role_ids.each do |id|
292
        role = Role.find(id)
293
294
        # Admins are able to remove the admin role from other users. All other roles may only
295
        # remove roles with a higher priority
296
        if (role.priority > current_user_role.priority || current_user_role.name == "admin") &&
297
           role.provider == @user_domain
298
          removed_roles << role
299
        else
300
          flash[:alert] = I18n.t("administrator.roles.invalid_removal")
301
          return false
302
        end
303
      end
304
305
      # Send promoted/demoted emails
306
      added_roles.each { |role| send_user_promoted_email(@user, role.name) if role.send_promoted_email }
307
      removed_roles.each { |role| send_user_demoted_email(@user, role.name) if role.send_demoted_email }
308
309
      # Update the roles
310
      @user.roles.delete(removed_roles)
311
      @user.roles << added_roles
312
313
      # Make sure each user always has at least the user role
314
      @user.roles = [Role.find_by(name: "user", provider: @user_domain)] if @user.roles.count.zero?
315
316
      @user.save!
317
    else
318
      true
319
    end
320
  end
321
end
322