mconf/mconf-web

View on GitHub
app/controllers/spaces_controller.rb

Summary

Maintainability
B
6 hrs
Test Coverage
# -*- coding: utf-8 -*-
# This file is part of Mconf-Web, a web application that provides access
# to the Mconf webconferencing system. Copyright (C) 2010-2015 Mconf.
#
# This file is licensed under the Affero General Public License version
# 3 or later. See the LICENSE file.

class SpacesController < InheritedResources::Base
  include Mconf::ApprovalControllerModule # for approve, disapprove
  include Mconf::DisableControllerModule # for enable, disable
  include Mconf::SelectControllerModule # select

  before_filter :require_spaces_mod

  before_filter :authenticate_user!, :only => [:new, :create]

  # TODO: cleanup the other actions adding respond_to blocks here
  respond_to :js, :only => [:index, :show]
  respond_to :json, :only => [:update_logo]
  respond_to :html, :only => [:new, :edit, :index, :show, :destroy, :update]

  rescue_from ActiveRecord::RecordNotFound, :with => :handle_record_not_found

  # Cancan and inherited resources load
  defaults finder: :find_by_slug!
  before_filter :load_space_via_space_id, only: [:edit_recording]
  before_filter :load_spaces_index, only: [:index, :select]
  load_and_authorize_resource :find_by => :slug, :except => [:enable, :disable, :destroy]
  before_filter :load_and_authorize_with_disabled, :only => [:enable, :disable, :destroy]

  # all actions that render the web conference room snippet
  before_filter :webconf_room!, :only => [:show, :webconference, :meetings]

  before_filter :load_spaces_examples, only: [:new, :create]

  before_filter :load_events, only: :show

  # Create recent activity
  after_filter :only => [:create, :update, :update_logo, :leave] do
    @space.new_activity(params[:action], current_user) unless @space.errors.any?
  end

  # modals
  before_filter :force_modal, only: :edit_recording

  layout :determine_layout

  def determine_layout
    case params[:action].to_sym
    when :new, :create
      "navbar_bg"
    when :edit_recording
      false
    else
      "application"
    end
  end

  def index
    order_spaces
    paginate_spaces

    if request.xhr?
      render "spaces/_list_view", layout: false, locals: { spaces: @spaces, user_spaces: @user_spaces , extended: true }
    else
      set_menu_tab
      render :index
    end
  end

  def show
    @latest_posts = @space.latest_posts
    @latest_users = @space.latest_users
  end

  def create
    if @space.save
      respond_with @space do |format|

        # the user that created the space is always an admin
        @space.add_member!(current_user, 'Admin')

        # pre-approve the space if it's an admin creating it
        @space.approve! if can?(:approve, @space)

        flash[:notice] = if @space.approved?
          t('space.created')
        else
          t('space.created_waiting_moderation')
        end

        format.html { redirect_to action: "show", id: @space }
      end
    else
      respond_with @space do |format|
        format.html { render :new }
      end
    end
  end

  def update_logo
    @space.logo_image = params[:uploaded_file]

    if @space.save
      url = logo_images_crop_path(model_type: 'space', model_id: @space)
      respond_to do |format|
        format.json {
          render json: {
                   success: true, redirect_url: url, small_image: @space.small_logo_image?,
                   new_url: @space.logo_image.url
                 }
        }
      end
    else
      respond_to do |format|
        format.json { render json: { success: false } }
      end
    end
  end

  def update
    unless params[:space][:bigbluebutton_room_attributes].blank?
      params[:space][:bigbluebutton_room_attributes][:id] = @space.bigbluebutton_room.id
    end

    update! { :back }
  end

  def destroy
    destroy!(notice: t('space.deleted')) { manage_spaces_path }
  end

  def user_permissions
    @users = @space.users.order("name ASC")
    @permissions = @space.permissions_ordered_by_name
      .paginate(:page => params[:page], :per_page => 10)
    @roles = Space.roles
  end

  def leave
    permission = @space.permissions.find_by_user_id(current_user)

    if permission
      permission.destroy
      respond_to do |format|
        format.html {
          flash[:success] = t('space.leave.success', :space_name => @space.name)
          if can?(:show, @space)
            redirect_to space_path(@space)
          else
            redirect_to root_path
          end
        }
      end
    else
      respond_to do |format|
        format.html { redirect_to space_path(@space) }
      end
    end
  end

  # Action used to show a webconference room of a space
  # This action is here and not in CustomBigbluebuttonRoomsController because it seems out of place
  # there, the before_filters and other methods don't really match. It's more related to spaces then
  # to webconference rooms.
  def webconference
    @webconf_attendees = @webconf_room.current_attendees
    @meetings = BigbluebuttonMeeting.where(room: @webconf_room).with_recording().newest(5)
  end

  # Action used to show the meetings of a space
  # This action is here and not in CustomBigbluebuttonRoomsController because it seems out of place
  # there, the before_filters and other methods don't really match. It's more related to spaces then
  # to webconference rooms.
  def meetings

    @meetings = BigbluebuttonMeeting.where(room: @webconf_room)
    if params[:recordedonly] == 'false'
      @meetings = @meetings.with_or_without_recording()
    else
      @meetings = @meetings.with_recording()
    end
    @meetings = @meetings.newest

    @recording_count = @meetings.count
    if params[:limit]
      @meetings = @meetings.first(params[:limit].to_i)
    end
  end

  # Page to edit a recording.
  def edit_recording
    @redir_url = request.referer
    @recording = BigbluebuttonRecording.find_by_recordid(params[:id])
    authorize! :space_edit, @recording
  end

  private

  # Load the @spaces and @user_spaces variables
  # The @spaces variable will only contain approved spaces
  def load_spaces_index
    spaces = Space.where(approved: true)
    @user_spaces = user_signed_in? ? current_user.spaces : Space.none
    words = params[:q].try(:split, /\s+/)

    @spaces = params[:my_spaces] ? @user_spaces : spaces
    @spaces = params[:q] ? @spaces.search_by_terms(words, can?(:manage, Space)) : @spaces

    params[:tag] = "" if params[:tag].blank? || !params[:tag].split(ActsAsTaggableOn.delimiter).any?
    @spaces = params[:tag].blank? ? @spaces : @spaces.tagged_with(params[:tag])

    @spaces = @spaces.includes(:tags)
  end

  def order_spaces
    params[:order] = 'relevance' if params[:order].nil? || params[:order] != 'abc'

    if params[:order] == 'abc'
      @spaces = @spaces.order('name ASC')
    else
      @spaces = @spaces.order_by_relevance
    end
  end

  def paginate_spaces
    @spaces = @spaces.paginate(:page => params[:page], :per_page => 15)
  end

  # Should be on the view?
  def set_menu_tab
    session[:current_tab] = "Spaces" if @space

    if params[:manage]
      session[:current_tab] = "Manage"
      session[:current_sub_tab] = "Spaces"
    end
  end

  def load_and_authorize_with_disabled
    @space = Space.with_disabled.find_by(slug: params[:id])
    authorize! action_name.to_sym, @space
  end

  def load_spaces_examples
    # TODO: RAND() is specific for mysql
    @spaces_examples = Space.where(approved: true).order_by_activity.limit(20).sample(5)
  end

  def load_events
    @upcoming_events = @space.events.upcoming.order("start_on ASC").first(5)
    @current_events = @space.events.order("start_on ASC").select(&:is_happening_now?)
  end

  # For edit_recording
  def load_space_via_space_id
    @space = Space.find_by(slug: params[:space_id])
  end

  def handle_record_not_found(exception)
    @error_message = t("spaces.error.not_found", :slug => params[:id], :path => spaces_path)
    render_404 exception
  end

  # Custom handler for access denied errors, overrides method on ApplicationController.
  # Used to show messages better than a simple 403 for the users in some cases.
  def handle_access_denied(exception)

    # anonymous users are required to sign in
    if !user_signed_in?
      redirect_to login_path

    # if it's a logged user that tried to access a private or unnaproved space
    elsif [:show, :edit].include?(exception.action)

      if !@space.approved?
        flash[:error] = t("spaces.error.unapproved")
        redirect_to spaces_path
      else
        # redirect him to the page to ask permission to join
        # if the user already has a pending request, it will have a notice and links to
        # access the invitation/request
        redirect_to new_space_join_request_path(space_id: params[:id])
      end

    # when space creation is forbidden for users
    elsif [:create, :new].include?(exception.action)
      flash[:error] = t("spaces.error.creation_forbidden")
      redirect_to spaces_path

    # when the user can't leave the space because it's the last admin
    elsif [:leave].include?(exception.action) && @space.is_last_admin?(current_user)
      flash[:error] = t("spaces.error.last_admin_cant_leave")
      redirect_to space_path(@space)

    # destructive actions are redirected to the 403 error
    else
      flash[:error] = t("space.access_forbidden")
      if exception.action == :show
        @error_message = t("space.is_private_html", name: @space.name, path: new_space_join_request_path(@space))
      end
      render_403 exception
    end
  end

  def require_approval?
    current_site.require_space_approval?
  end

  allow_params_for :space
  def allowed_params
    [ :name, :description, :logo_image, :public, :slug, :disabled, :repository,
      :crop_x, :crop_y, :crop_w, :crop_h, :crop_img_w, :crop_img_h, :tag_list,
      :bigbluebutton_room_attributes =>
        [ :id, :attendee_key, :moderator_key, :default_layout, :private, :welcome_msg ]
    ]
  end

  # For disable controller module
  def disable_back_path
    if request.referer.present? && request.referer.include?("manage") && current_user.superuser?
      manage_spaces_path
    else
      spaces_path
    end
  end

  def back_url
    request.referer
  end
end