ece517-p3/expertiza

View on GitHub
app/controllers/users_controller.rb

Summary

Maintainability
C
1 day
Test Coverage
require 'will_paginate/array'

class UsersController < ApplicationController
  autocomplete :user, :name
  # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
  verify method: :post, only: %i[destroy create update],
         redirect_to: {action: :list}

  def action_allowed?
    case params[:action]
    when 'list_pending_requested'
      ['Super-Administrator',
       'Administrator'].include? current_role_name
    when 'request_new'
      true
    when 'create_requested_user_record'
      true
    when 'keys'
      current_role_name.eql? 'Student'
    else
      ['Super-Administrator',
       'Administrator',
       'Instructor',
       'Teaching Assistant'].include? current_role_name
    end
  end

  def index
    if current_user_role? == "Student"
      redirect_to(action: AuthHelper.get_home_action(session[:user]), controller: AuthHelper.get_home_controller(session[:user]))
    else
      list
      render action: 'list'
    end
  end

  def auto_complete_for_user_name
    user = session[:user]
    role = Role.find(user.role_id)
    @users = User.where('name LIKE ? and (role_id in (?) or id = ?)', "#{params[:user][:name]}%", role.get_available_roles, user.id)
    render inline: "<%= auto_complete_result @users, 'name' %>", layout: false
  end

  #
  # for anonymized view for demo purposes
  #
  def set_anonymized_view
    anonymized_view_starter_ips = $redis.get('anonymized_view_starter_ips') || ''
    session[:ip] = request.remote_ip
    if anonymized_view_starter_ips.include? session[:ip]
      anonymized_view_starter_ips.delete!(" #{session[:ip]}")
    else
      anonymized_view_starter_ips += " #{session[:ip]}"
    end
    $redis.set('anonymized_view_starter_ips', anonymized_view_starter_ips)
    redirect_to :back
  end

  # for displaying the list of users
  def list
    user = session[:user]
    @users = user.get_user_list
  end

  def list_pending_requested
    @requested_users = RequestedUser.all
    @roles = Role.all
  end

  def show_selection
    @user = User.find_by(name: params[:user][:name])
    if !@user.nil?
      get_role
      if @role.parent_id.nil? || @role.parent_id < session[:user].role_id || @user.id == session[:user].id
        render action: 'show'
      else
        flash[:note] = 'The specified user is not available for editing.'
        redirect_to action: 'list'
      end
    else
      flash[:note] = params[:user][:name] + ' does not exist.'
      redirect_to action: 'list'
    end
  end

  def show
    if params[:id].nil? || ((current_user_role? == "Student") && (session[:user].id != params[:id].to_i))
      redirect_to(action: AuthHelper.get_home_action(session[:user]), controller: AuthHelper.get_home_controller(session[:user]))
    else
      @user = User.find(params[:id])
      get_role
      # obtain number of assignments participated
      @assignment_participant_num = 0
      AssignmentParticipant.where(user_id: @user.id).each {|_participant| @assignment_participant_num += 1 }
      # judge whether this user become reviewer or reviewee
      @maps = ResponseMap.where('reviewee_id = ? or reviewer_id = ?', params[:id], params[:id])
      # count the number of users in DB
      @total_user_num = User.count
    end
  end

  def new
    @user = User.new
    @rolename = Role.find_by(name: params[:role])
    foreign
  end

  def request_new
    flash[:warn] = "If you are a student, please contact your teaching staff to get your Expertiza ID."
    @user = User.new
    @rolename = Role.find_by(name: params[:role])
    roles_for_request_sign_up
  end

  def create
    # if the user name already exists, register the user by email address
    check = User.find_by(name: params[:user][:name])
    params[:user][:name] = params[:user][:email] unless check.nil?
    @user = User.new(user_params)
    @user.institution_id = params[:user][:institution_id]
    # record the person who created this new user
    @user.parent_id = session[:user].id
    # set the user's timezone to its parent's
    @user.timezonepref = User.find(@user.parent_id).timezonepref
    if @user.save
      password = @user.reset_password # the password is reset
      prepared_mail = MailerHelper.send_mail_to_user(@user, "Your Expertiza account and password have been created.", "user_welcome", password)
      prepared_mail.deliver
      flash[:success] = "A new password has been sent to new user's e-mail address."
      # Instructor and Administrator users need to have a default set for their notifications
      # the creation of an AssignmentQuestionnaire object with only the User ID field populated
      # ensures that these users have a default value of 15% for notifications.
      # TAs and Students do not need a default. TAs inherit the default from the instructor,
      # Students do not have any checks for this information.
      AssignmentQuestionnaire.create(user_id: @user.id) if @user.role.name == "Instructor" or @user.role.name == "Administrator"
      undo_link("The user \"#{@user.name}\" has been successfully created. ")
      redirect_to action: 'list'
    else
      foreign
      render action: 'new'
    end
  end

  def create_requested_user_record
    requested_user = RequestedUser.new(requested_user_params)
    if params[:user][:institution_id].empty?
      institution = Institution.find_or_create_by(name: params[:institution][:name])
      requested_user.institution_id = institution.id
    end
    requested_user.status = 'Under Review'
    # The super admin receives a mail about a new user request with the user name
    user_existed = User.find_by(name: requested_user.name) or User.find_by(name: requested_user.email)
    requested_user_saved = requested_user.save
    if !user_existed and requested_user_saved
      super_users = User.joins(:role).where('roles.name = ?', 'Super-Administrator')
      super_users.each do |super_user|
        prepared_mail = MailerHelper.send_mail_to_all_super_users(super_user, requested_user, 'New account Request')
        prepared_mail.deliver
      end
      ExpertizaLogger.info LoggerMessage.new(controller_name, requested_user.name, 'The account you are requesting has been created successfully.', request)
      flash[:success] = "User signup for \"#{requested_user.name}\" has been successfully requested."
      redirect_to '/instructions/home'
      return
    elsif user_existed
      flash[:error] = "The account you are requesting has already existed in Expertiza."
    else
      flash[:error] = requested_user.errors.full_messages.to_sentence
    end
    ExpertizaLogger.error LoggerMessage.new(controller_name, requested_user.name, flash[:error], request)
    redirect_to controller: 'users', action: 'request_new', role: 'Student'
  end

  def create_approved_user
    requested_user = RequestedUser.find_by(id: params[:id])
    requested_user.status = params[:status]
    if requested_user.status.nil?
      flash[:error] = "Please Approve or Reject before submitting"
    elsif requested_user.update_attributes(params[:user])
      flash[:success] = "The user \"#{requested_user.name}\" has been successfully updated."
    end
    if requested_user.status == "Approved"
      new_user = User.new
      new_user.name = requested_user.name
      new_user.role_id = requested_user.role_id
      new_user.institution_id = requested_user.institution_id
      new_user.fullname = requested_user.fullname
      new_user.email = requested_user.email
      new_user.parent_id = session[:user].id
      new_user.timezonepref = User.find_by(id: new_user.parent_id).timezonepref
      if new_user.save
        password = new_user.reset_password
        # Mail is sent to the user with a new password
        prepared_mail = MailerHelper.send_mail_to_user(new_user, "Your Expertiza account and password have been created.", "user_welcome", password)
        prepared_mail.deliver
        flash[:success] = "A new password has been sent to new user's e-mail address."
        undo_link("The user \"#{requested_user.name}\" has been successfully created. ")
      else
        foreign
      end
    elsif requested_user.status == "Rejected"
      # If the user request has been rejected, a flash message is shown and redirected to review page
      if requested_user.update_columns(status: params[:status])
        flash[:success] = "The user \"#{requested_user.name}\" has been Rejected."
        redirect_to action: 'list_pending_requested'
        return
      else
        flash[:error] = "Error processing request."
      end
    end
    redirect_to action: 'list_pending_requested'
  end

  def edit
    @user = User.find(params[:id])
    get_role
    foreign
  end

  def update
    params.permit!
    @user = User.find params[:id]
    # update username, when the user cannot be deleted
    # rename occurs in 'show' page, not in 'edit' page
    # eg. /users/5408?name=5408
    @user.name += '_hidden' if request.original_fullpath == "/users/#{@user.id}?name=#{@user.id}"

    if @user.update_attributes(params[:user])
      flash[:success] = "The user \"#{@user.name}\" has been successfully updated."
      redirect_to @user
    else
      render action: 'edit'
    end
  end

  def destroy
    begin
      @user = User.find(params[:id])
      AssignmentParticipant.where(user_id: @user.id).each(&:delete)
      TeamsUser.where(user_id: @user.id).each(&:delete)
      AssignmentQuestionnaire.where(user_id: @user.id).each(&:destroy)
      # Participant.delete(true)
      @user.destroy
      flash[:note] = "The user \"#{@user.name}\" has been successfully deleted."
    rescue StandardError
      flash[:error] = $ERROR_INFO
    end

    redirect_to action: 'list'
  end

  def keys
    if params[:id].nil? || ((current_user_role? == "Student") && (session[:user].id != params[:id].to_i))
      redirect_to(action: AuthHelper.get_home_action(session[:user]), controller: AuthHelper.get_home_controller(session[:user]))
    else
      @user = User.find(params[:id])
      @private_key = @user.generate_keys
    end
  end

  protected

  def foreign
    role = Role.find(session[:user].role_id)
    @all_roles = Role.where('id in (?) or id = ?', role.get_available_roles, role.id)
  end

  def roles_for_request_sign_up
    roles_can_be_requested_online = ["Instructor", "Teaching Assistant"]
    @all_roles = Role.where(name: roles_can_be_requested_online)
  end

  private

  def user_params
    params.require(:user).permit(:name,
                                 :crypted_password,
                                 :role_id,
                                 :password_salt,
                                 :fullname,
                                 :email,
                                 :parent_id,
                                 :private_by_default,
                                 :mru_directory_path,
                                 :email_on_review,
                                 :email_on_submission,
                                 :email_on_review_of_review,
                                 :is_new_user,
                                 :master_permission_granted,
                                 :handle,
                                 :digital_certificate,
                                 :persistence_token,
                                 :timezonepref,
                                 :public_key,
                                 :copy_of_emails,
                                 :institution_id)
  end

  def requested_user_params
    params.require(:user).permit(:name, :role_id, :fullname, :institution_id, :email)
          .merge(self_introduction: params[:requested_user][:self_introduction])
  end

  def get_role
    if @user && @user.role_id
      @role = Role.find(@user.role_id)
    elsif @user
      @role = Role.new(id: nil, name: '(none)')
    end
  end

  # For filtering the users list with proper search and pagination.
  def paginate_list(users)
    paginate_options = {"1" => 25, "2" => 50, "3" => 100}

    # If the above hash does not have a value for the key,
    # it means that we need to show all the users on the page
    #
    # Just a point to remember, when we use pagination, the
    # 'users' variable should be an object, not an array

    # The type of condition for the search depends on what the user has selected from the search_by dropdown
    @search_by = params[:search_by]

    # search for corresponding users
    # users = User.search_users(role, user_id, letter, @search_by)

    # paginate
    users = if paginate_options[@per_page.to_s].nil? # displaying all - no pagination
              User.paginate(page: params[:page], per_page: users.count)
            else # some pagination is active - use the per_page
              User.paginate(page: params[:page], per_page: paginate_options[@per_page.to_s])
            end
    users
  end

  # generate the undo link
  # def undo_link
  #  "<a href = #{url_for(:controller => :versions,:action => :revert,:id => @user.versions.last.id)}>undo</a>"
  # end
end