From fd6077696d2233efc1697ace192e702285d531b0 Mon Sep 17 00:00:00 2001 From: farhatahmad <35435341+farhatahmad@users.noreply.github.com> Date: Mon, 19 Aug 2019 11:28:48 -0400 Subject: [PATCH 1/9] GRN2-180: First stages of refactoring code for v2.4 (#748) * Email rescues and authenticator concern * Application controller and helper clean up * Moved controller code out of helpers * More helper and email clean up * Cleaned up remaining helpers and create omniauth_options * Controller code clean up * restructured views structure * Restructured role code * Restructured profile and code clean up * Master merge * Added bbb server concern to deal with bbb calls * Bug fixes and changes after changes * rspec * More rubocop fixes --- app/assets/javascripts/admins.js | 8 +- .../account_activations_controller.rb | 31 +-- app/controllers/admins_controller.rb | 199 +++------------- app/controllers/application_controller.rb | 224 ++++++++++-------- .../concerns/authenticator.rb} | 70 +----- app/controllers/concerns/bbb_server.rb | 109 +++++++++ app/controllers/concerns/emailer.rb | 105 +++++--- app/controllers/concerns/recorder.rb | 14 +- app/controllers/concerns/registrar.rb | 12 +- app/controllers/concerns/rolify.rb | 161 +++++++++++++ app/controllers/password_resets_controller.rb | 37 +-- app/controllers/recordings_controller.rb | 12 +- app/controllers/rooms_controller.rb | 128 +++++----- app/controllers/sessions_controller.rb | 109 +++++---- app/controllers/themes_controller.rb | 7 - app/controllers/users_controller.rb | 143 +++-------- app/helpers/account_activations_helper.rb | 20 -- app/helpers/admins_helper.rb | 30 +-- app/helpers/application_helper.rb | 69 +----- app/helpers/errors_helper.rb | 20 -- app/helpers/main_helper.rb | 20 -- app/helpers/meetings_helper.rb | 20 -- app/helpers/password_resets_helper.rb | 20 -- app/helpers/recordings_helper.rb | 7 +- app/helpers/rooms_helper.rb | 18 +- app/helpers/theming_helper.rb | 17 +- app/helpers/users_helper.rb | 29 +++ app/mailers/application_mailer.rb | 1 - app/mailers/user_mailer.rb | 57 +++-- app/models/ability.rb | 3 +- app/models/room.rb | 106 --------- app/models/user.rb | 9 +- .../{verify.html.erb => show.html.erb} | 4 +- .../components/_admins_role.html.erb | 0 .../components/_admins_tags.html.erb | 0 .../admins/components/_settings.html.erb | 30 +-- app/views/admins/components/_users.html.erb | 4 +- app/views/admins/edit_user.html.erb | 2 +- .../components}/_features.html.erb | 0 app/views/main/index.html.erb | 2 +- .../components/_create_room_block.html.erb | 0 .../components/_room_block.html.erb | 0 .../components}/_room_event.html.erb | 0 app/views/rooms/join.html.erb | 4 +- app/views/rooms/show.html.erb | 10 +- app/views/rooms/wait.html.erb | 2 +- .../shared/components/_resend_button.html.erb | 18 -- .../shared/components/_subtitle.html.erb | 13 +- .../shared/components/_terms_button.html.erb | 18 -- .../shared/modals/_delete_room_modal.html.erb | 4 +- .../change_password.html.erb} | 12 +- .../components}/_account.html.erb | 0 .../components}/_delete.html.erb | 0 .../users/components/_menu_buttons.html.erb | 26 ++ .../components}/_password.html.erb | 0 .../components}/_setting_view.html.erb | 4 +- .../delete_account.html.erb} | 10 +- app/views/users/edit.html.erb | 37 +-- app/views/users/terms.html.erb | 4 +- config/initializers/omniauth.rb | 5 +- config/locales/en.yml | 10 +- config/routes.rb | 26 +- lib/omniauth_options.rb | 71 ++++++ spec/concerns/bbb_server_spec.rb | 88 +++++++ spec/concerns/recorder_spec.rb | 32 +-- .../account_activations_controller_spec.rb | 2 +- spec/controllers/admins_controller_spec.rb | 30 +-- .../application_controller_spec.rb | 64 ++++- .../password_resets_controller_spec.rb | 6 +- .../controllers/recordings_controller_spec.rb | 12 +- spec/controllers/rooms_controller_spec.rb | 25 +- spec/controllers/users_controller_spec.rb | 3 +- spec/helpers/admins_helper_spec.rb | 44 ---- spec/helpers/application_helper_spec.rb | 62 +---- spec/helpers/users_helper_spec.rb | 44 ---- spec/models/room_spec.rb | 74 ------ 76 files changed, 1187 insertions(+), 1430 deletions(-) rename app/{helpers/sessions_helper.rb => controllers/concerns/authenticator.rb} (54%) create mode 100644 app/controllers/concerns/bbb_server.rb create mode 100644 app/controllers/concerns/rolify.rb delete mode 100644 app/helpers/account_activations_helper.rb delete mode 100644 app/helpers/errors_helper.rb delete mode 100644 app/helpers/main_helper.rb delete mode 100644 app/helpers/meetings_helper.rb delete mode 100644 app/helpers/password_resets_helper.rb rename app/views/account_activations/{verify.html.erb => show.html.erb} (83%) rename app/views/{shared => admins}/components/_admins_role.html.erb (100%) rename app/views/{shared => admins}/components/_admins_tags.html.erb (100%) rename app/views/{shared => main/components}/_features.html.erb (100%) rename app/views/{shared => rooms}/components/_create_room_block.html.erb (100%) rename app/views/{shared => rooms}/components/_room_block.html.erb (100%) rename app/views/{shared => rooms/components}/_room_event.html.erb (100%) delete mode 100644 app/views/shared/components/_resend_button.html.erb delete mode 100644 app/views/shared/components/_terms_button.html.erb rename app/views/{shared/components/_confirm_button.html.erb => users/change_password.html.erb} (67%) rename app/views/{shared/settings => users/components}/_account.html.erb (100%) rename app/views/{shared/settings => users/components}/_delete.html.erb (100%) create mode 100644 app/views/users/components/_menu_buttons.html.erb rename app/views/{shared/settings => users/components}/_password.html.erb (100%) rename app/views/{shared/settings => users/components}/_setting_view.html.erb (92%) rename app/views/{shared/settings/_design.html.erb => users/delete_account.html.erb} (70%) create mode 100644 lib/omniauth_options.rb create mode 100644 spec/concerns/bbb_server_spec.rb delete mode 100644 spec/helpers/admins_helper_spec.rb delete mode 100644 spec/helpers/users_helper_spec.rb diff --git a/app/assets/javascripts/admins.js b/app/assets/javascripts/admins.js index 88521567..a7a4245e 100644 --- a/app/assets/javascripts/admins.js +++ b/app/assets/javascripts/admins.js @@ -79,7 +79,7 @@ $(document).on('turbolinks:load', function(){ // Change the branding image to the image provided function changeBrandingImage(path) { var url = $("#branding-url").val() - $.post(path, {url: url}) + $.post(path, {value: url}) } // Filters by role @@ -157,19 +157,19 @@ function loadColourSelectors() { }); pickrRegular.on("save", (color, instance) => { - $.post($("#coloring-path-regular").val(), {color: color.toHEXA().toString()}).done(function() { + $.post($("#coloring-path-regular").val(), {value: color.toHEXA().toString()}).done(function() { location.reload() }); }) pickrLighten.on("save", (color, instance) => { - $.post($("#coloring-path-lighten").val(), {color: color.toHEXA().toString()}).done(function() { + $.post($("#coloring-path-lighten").val(), {value: color.toHEXA().toString()}).done(function() { location.reload() }); }) pickrDarken.on("save", (color, instance) => { - $.post($("#coloring-path-darken").val(), {color: color.toHEXA().toString()}).done(function() { + $.post($("#coloring-path-darken").val(), {value: color.toHEXA().toString()}).done(function() { location.reload() }); }) diff --git a/app/controllers/account_activations_controller.rb b/app/controllers/account_activations_controller.rb index fd7450c3..cc859f09 100644 --- a/app/controllers/account_activations_controller.rb +++ b/app/controllers/account_activations_controller.rb @@ -24,46 +24,45 @@ class AccountActivationsController < ApplicationController # GET /account_activations def show - render :verify end # GET /account_activations/edit def edit + # If the user exists and is not verified and provided the correct token if @user && !@user.activated? && @user.authenticated?(:activation, params[:token]) + # Verify user @user.activate # Redirect user to root with account pending flash if account is still pending return redirect_to root_path, flash: { success: I18n.t("registration.approval.signup") } if @user.has_role?(:pending) - flash[:success] = I18n.t("verify.activated") + " " + I18n.t("verify.signin") - redirect_to signin_path + # Redirect user to sign in path with success flash + redirect_to signin_path, flash: { success: I18n.t("verify.activated") + " " + I18n.t("verify.signin") } else - flash[:alert] = I18n.t("verify.invalid") - redirect_to root_path + redirect_to root_path, flash: { alert: I18n.t("verify.invalid") } end end # GET /account_activations/resend def resend if @user.activated? + # User is already verified flash[:alert] = I18n.t("verify.already_verified") else - begin - send_activation_email(@user) - rescue => e - logger.error "Support: Error in email delivery: #{e}" - flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) - else - flash[:success] = I18n.t("email_sent", email_type: t("verify.verification")) - end + # Resend + send_activation_email(@user) end - redirect_to(root_path) + redirect_to root_path end private + def find_user + @user = User.find_by!(email: params[:email], provider: @user_domain) + end + def ensure_unauthenticated redirect_to current_user.main_room if current_user end @@ -71,8 +70,4 @@ class AccountActivationsController < ApplicationController def email_params params.require(:email).permit(:email, :token) end - - def find_user - @user = User.find_by!(email: params[:email], provider: @user_domain) - end end diff --git a/app/controllers/admins_controller.rb b/app/controllers/admins_controller.rb index b1c9d48b..1b52e585 100644 --- a/app/controllers/admins_controller.rb +++ b/app/controllers/admins_controller.rb @@ -21,18 +21,17 @@ class AdminsController < ApplicationController include Themer include Emailer include Recorder + include Rolify manage_users = [:edit_user, :promote, :demote, :ban_user, :unban_user, :approve, :reset] - site_settings = [:branding, :coloring, :coloring_lighten, :coloring_darken, - :registration_method, :room_authentication, :room_limit, :default_recording_visibility] authorize_resource class: false before_action :find_user, only: manage_users before_action :verify_admin_of_user, only: manage_users - before_action :find_setting, only: site_settings # GET /admins def index + # Initializa the data manipulation variables @search = params[:search] || "" @order_column = params[:column] && params[:direction] != "none" ? params[:column] : "created_at" @order_direction = params[:direction] && params[:direction] != "none" ? params[:direction] : "DESC" @@ -49,13 +48,14 @@ class AdminsController < ApplicationController # GET /admins/server_recordings def server_recordings server_rooms = if Rails.configuration.loadbalanced_configuration - Room.includes(:owner).where(users: { provider: user_settings_provider }).pluck(:bbb_id) + Room.includes(:owner).where(users: { provider: @user_domain }).pluck(:bbb_id) else Room.pluck(:bbb_id) end @search, @order_column, @order_direction, recs = - all_recordings(server_rooms, @user_domain, params.permit(:search, :column, :direction), true, true) + all_recordings(server_rooms, params.permit(:search, :column, :direction), true, true) + @pagy, @recordings = pagy_array(recs) end @@ -92,17 +92,10 @@ class AdminsController < ApplicationController def invite emails = params[:invite_user][:email].split(",") - begin - emails.each do |email| - invitation = create_or_update_invite(email) + emails.each do |email| + invitation = create_or_update_invite(email) - send_invitation_email(current_user.name, email, invitation.invite_token) - end - rescue => e - logger.error "Support: Error in email delivery: #{e}" - flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) - else - flash[:success] = I18n.t("administrator.flash.invite", email: emails.join(', ')) + send_invitation_email(current_user.name, email, invitation.invite_token) end redirect_to admins_path @@ -118,39 +111,30 @@ class AdminsController < ApplicationController end # SITE SETTINGS - # POST /admins/branding - def branding - @settings.update_value("Branding Image", params[:url]) - redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } + # POST /admins/update_settings + def update_settings + @settings.update_value(params[:setting], params[:value]) + + flash_message = I18n.t("administrator.flash.settings") + + if params[:value] == "Default Recording Visibility" + flash_message += ". " + I18n.t("administrator.site_settings.recording_visibility.warning") + end + + redirect_to admin_site_settings_path, flash: { success: flash_message } end # POST /admins/color def coloring - @settings.update_value("Primary Color", params[:color]) - @settings.update_value("Primary Color Lighten", color_lighten(params[:color])) - @settings.update_value("Primary Color Darken", color_darken(params[:color])) - redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } - end - - def coloring_lighten - @settings.update_value("Primary Color Lighten", params[:color]) - redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } - end - - def coloring_darken - @settings.update_value("Primary Color Darken", params[:color]) - redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } - end - - # POST /admins/room_authentication - def room_authentication - @settings.update_value("Room Authentication", params[:value]) + @settings.update_value("Primary Color", params[:value]) + @settings.update_value("Primary Color Lighten", color_lighten(params[:value])) + @settings.update_value("Primary Color Darken", color_darken(params[:value])) redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } end # POST /admins/registration_method/:method def registration_method - new_method = Rails.configuration.registration_methods[params[:method].to_sym] + new_method = Rails.configuration.registration_methods[params[:value].to_sym] # Only allow change to Join by Invitation if user has emails enabled if !Rails.configuration.enable_email_verification && new_method == Rails.configuration.registration_methods[:invite] @@ -163,67 +147,19 @@ class AdminsController < ApplicationController end end - # POST /admins/room_limit - def room_limit - @settings.update_value("Room Limit", params[:limit]) - redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } - end - - # POST /admins/default_recording_visibility - def default_recording_visibility - @settings.update_value("Default Recording Visibility", params[:visibility]) - redirect_to admin_site_settings_path, flash: { - success: I18n.t("administrator.flash.settings") + ". " + - I18n.t("administrator.site_settings.recording_visibility.warning") - } - end - - # POST /admins/clear_cache - def clear_cache - Rails.cache.delete("#{@user_domain}/getUser") - Rails.cache.delete("#{@user_domain}/getUserGreenlightCredentials") - - redirect_to admin_site_settings_path, flash: { success: I18n.t("administrator.flash.settings") } - end - # ROLES # GET /admins/roles def roles - @roles = Role.editable_roles(@user_domain) - - if @roles.count.zero? - Role.create_default_roles(@user_domain) - @roles = Role.editable_roles(@user_domain) - end - - @selected_role = if params[:selected_role].nil? - @roles.find_by(name: 'user') - else - @roles.find(params[:selected_role]) - end + @roles = all_roles(params[:selected_role]) end - # POST /admin/role - # This method creates a new role scope to the users provider + # POST /admins/role + # This method creates a new role scoped to the users provider def new_role - new_role_name = params[:role][:name] + new_role = create_role(params[:role][:name]) - # Make sure that the role name isn't a duplicate or a reserved name like super_admin - if Role.duplicate_name(new_role_name, @user_domain) - flash[:alert] = I18n.t("administrator.roles.duplicate_name") - - return redirect_to admin_roles_path - end - - # Make sure the role name isn't empty - if new_role_name.strip.empty? - flash[:alert] = I18n.t("administrator.roles.empty_name") - - return redirect_to admin_roles_path - end - - new_role = Role.create_new_role(new_role_name, @user_domain) + return redirect_to admin_roles_path, flash: { alert: I18n.t("administrator.roles.invalid_create") } if new_role.nil? redirect_to admin_roles_path(selected_role: new_role.id) end @@ -232,82 +168,16 @@ class AdminsController < ApplicationController # This updates the priority of a site's roles # Note: A lower priority role will always get used before a higher priority one def change_role_order - user_role = Role.find_by(name: "user", provider: @user_domain) - admin_role = Role.find_by(name: "admin", provider: @user_domain) - - current_user_role = current_user.highest_priority_role - - # Users aren't allowed to update the priority of the admin or user roles - if params[:role].include?(user_role.id.to_s) || params[:role].include?(admin_role.id.to_s) - flash[:alert] = I18n.t("administrator.roles.invalid_order") - - return redirect_to admin_roles_path + unless update_priority(params[:role]) + redirect_to admin_roles_path, flash: { alert: I18n.t("administrator.roles.invalid_order") } end - - # Restrict users to only updating the priority for roles in their domain with a higher - # priority - params[:role].each do |id| - role = Role.find(id) - if role.priority <= current_user_role.priority || role.provider != @user_domain - flash[:alert] = I18n.t("administrator.roles.invalid_update") - return redirect_to admin_roles_path - end - end - - # Update the roles priority including the user role - top_priority = 0 - - params[:role].each_with_index do |id, index| - new_priority = index + [current_user_role.priority, 0].max + 1 - top_priority = new_priority - Role.where(id: id).update_all(priority: new_priority) - end - - user_role.priority = top_priority + 1 - user_role.save! end # POST /admin/role/:role_id # This method updates the permissions assigned to a role def update_role role = Role.find(params[:role_id]) - current_user_role = current_user.highest_priority_role - - # Checks that it is valid for the provider to update the role - if role.priority <= current_user_role.priority || role.provider != @user_domain - flash[:alert] = I18n.t("administrator.roles.invalid_update") - return redirect_to admin_roles_path(selected_role: role.id) - end - - role_params = params.require(:role).permit(:name) - permission_params = params.require(:role) - .permit( - :can_create_rooms, - :send_promoted_email, - :send_demoted_email, - :can_edit_site_settings, - :can_edit_roles, - :can_manage_users, - :colour - ) - - # Role is a default role so users can't change the name - role_params[:name] = role.name if Role::RESERVED_ROLE_NAMES.include?(role.name) - - # Make sure if the user is updating the role name that the role name is valid - if role.name != role_params[:name] && !Role.duplicate_name(role_params[:name], @user_domain) && - !role_params[:name].strip.empty? - role.name = role_params[:name] - elsif role.name != role_params[:name] - flash[:alert] = I18n.t("administrator.roles.duplicate_name") - - return redirect_to admin_roles_path(selected_role: role.id) - end - - role.update(permission_params) - - role.save! - + flash[:alert] = I18n.t("administrator.roles.invalid_update") unless update_permissions(role) redirect_to admin_roles_path(selected_role: role.id) end @@ -337,10 +207,7 @@ class AdminsController < ApplicationController @user = User.where(uid: params[:user_uid]).includes(:roles).first end - def find_setting - @settings = Setting.find_or_create_by!(provider: user_settings_provider) - end - + # Verifies that admin is an administrator of the user in the action def verify_admin_of_user redirect_to admins_path, flash: { alert: I18n.t("administrator.flash.unauthorized") } unless current_user.admin_of?(@user) @@ -355,7 +222,7 @@ class AdminsController < ApplicationController end if Rails.configuration.loadbalanced_configuration - initial_list.where(provider: user_settings_provider) + initial_list.where(provider: @user_domain) .admins_search(@search, @role) .admins_order(@order_column, @order_direction) else diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1c2f857b..2b46e004 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -16,35 +16,65 @@ # You should have received a copy of the GNU Lesser General Public License along # with BigBlueButton; if not, see . -require 'bigbluebutton_api' - class ApplicationController < ActionController::Base - include ApplicationHelper - include SessionsHelper + include BbbServer include ThemingHelper - # Force SSL for loadbalancer configurations. before_action :redirect_to_https - before_action :set_user_domain + before_action :set_user_settings before_action :maintenance_mode? before_action :migration_error? - before_action :set_locale + before_action :user_locale before_action :check_admin_password before_action :check_user_role # Manually handle BigBlueButton errors rescue_from BigBlueButton::BigBlueButtonException, with: :handle_bigbluebutton_error - protect_from_forgery with: :exception + protect_from_forgery with: :exceptions - MEETING_NAME_LIMIT = 90 - USER_NAME_LIMIT = 32 + # Retrieves the current user. + def current_user + @current_user ||= User.where(id: session[:user_id]).includes(:roles).first - # Include user domain in lograge logs - def append_info_to_payload(payload) - super - payload[:host] = @user_domain + if Rails.configuration.loadbalanced_configuration + if @current_user && !@current_user.has_role?(:super_admin) && + @current_user.provider != @user_domain + @current_user = nil + session.clear + end + end + + @current_user + end + helper_method :current_user + + def bbb_server + @bbb_server ||= Rails.configuration.loadbalanced_configuration ? bbb(@user_domain) : bbb("greenlight") + end + + # Force SSL + def redirect_to_https + if Rails.configuration.loadbalanced_configuration && request.headers["X-Forwarded-Proto"] == "http" + redirect_to protocol: "https://" + end + end + + # Sets the user domain variable + def set_user_domain + if Rails.env.test? || !Rails.configuration.loadbalanced_configuration + @user_domain = "greenlight" + else + @user_domain = parse_user_domain(request.host) + + check_provider_exists + end + end + + # Sets the settinfs variable + def set_user_settings + @settings = Setting.find_or_create_by(provider: @user_domain) end # Show an information page when migration fails and there is a version error. @@ -52,8 +82,40 @@ class ApplicationController < ActionController::Base render :migration_error, status: 500 unless ENV["DB_MIGRATE_FAILED"].blank? end + # Sets the appropriate locale. + def user_locale(user = current_user) + locale = if user && user.language != 'default' + user.language + else + http_accept_language.language_region_compatible_from(I18n.available_locales) + end + I18n.locale = locale.tr('-', '_') unless locale.nil? + end + + # Checks to make sure that the admin has changed his password from the default + def check_admin_password + if current_user&.has_role?(:admin) && current_user.email == "admin@example.com" && + current_user&.greenlight_account? && current_user&.authenticate(Rails.configuration.admin_password_default) + + flash.now[:alert] = I18n.t("default_admin", + edit_link: edit_user_path(user_uid: current_user.uid) + "?setting=password").html_safe + end + end + + # Checks if the user is banned and logs him out if he is + def check_user_role + if current_user&.has_role? :denied + session.delete(:user_id) + redirect_to root_path, flash: { alert: I18n.t("registration.banned.fail") } + elsif current_user&.has_role? :pending + session.delete(:user_id) + redirect_to root_path, flash: { alert: I18n.t("registration.approval.fail") } + end + end + + # Redirects the user to a Maintenance page if turned on def maintenance_mode? - if Rails.configuration.maintenance_mode + if ENV["MAINTENANCE_MODE"] == "true" render "errors/greenlight_error", status: 503, formats: :html, locals: { status_code: 503, @@ -68,30 +130,6 @@ class ApplicationController < ActionController::Base end end - # Sets the appropriate locale. - def set_locale - update_locale(current_user) - end - - def update_locale(user) - locale = if user && user.language != 'default' - user.language - else - http_accept_language.language_region_compatible_from(I18n.available_locales) - end - I18n.locale = locale.tr('-', '_') unless locale.nil? - end - - def meeting_name_limit - MEETING_NAME_LIMIT - end - helper_method :meeting_name_limit - - def user_name_limit - USER_NAME_LIMIT - end - helper_method :user_name_limit - # Relative root helper (when deploying to subdirectory). def relative_root Rails.configuration.relative_url_root || "" @@ -105,34 +143,53 @@ class ApplicationController < ActionController::Base end helper_method :bigbluebutton_endpoint_default? - def recording_thumbnails? - Rails.configuration.recording_thumbnails + def allow_greenlight_accounts? + return Rails.configuration.allow_user_signup unless Rails.configuration.loadbalanced_configuration + return false unless @user_domain && !@user_domain.empty? && Rails.configuration.allow_user_signup + return false if @user_domain == "greenlight" + # Proceed with retrieving the provider info + begin + provider_info = retrieve_provider_info(@user_domain, 'api2', 'getUserGreenlightCredentials') + provider_info['provider'] == 'greenlight' + rescue => e + logger.error "Error in checking if greenlight accounts are allowed: #{e}" + false + end end - helper_method :recording_thumbnails? + helper_method :allow_greenlight_accounts? - def allow_greenlight_users? - allow_greenlight_accounts? + # Determine if Greenlight is configured to allow user signups. + def allow_user_signup? + Rails.configuration.allow_user_signup end - helper_method :allow_greenlight_users? + helper_method :allow_user_signup? - # Determines if a form field needs the is-invalid class. - def form_is_invalid?(obj, key) - 'is-invalid' unless obj.errors.messages[key].empty? + # Gets all configured omniauth providers. + def configured_providers + Rails.configuration.providers.select do |provider| + Rails.configuration.send("omniauth_#{provider}") + end end - helper_method :form_is_invalid? + helper_method :configured_providers - # Default, unconfigured meeting options. - def default_meeting_options - invite_msg = I18n.t("invite_message") - { - user_is_moderator: false, - meeting_logout_url: request.base_url + logout_room_path(@room), - meeting_recorded: true, - moderator_message: "#{invite_msg}\n\n#{request.base_url + room_path(@room)}", - host: request.host, - recording_default_visibility: Setting.find_or_create_by!(provider: user_settings_provider) - .get_value("Default Recording Visibility") == "public" - } + # Parses the url for the user domain + def parse_user_domain(hostname) + return hostname.split('.').first if Rails.configuration.url_host.empty? + Rails.configuration.url_host.split(',').each do |url_host| + return hostname.chomp(url_host).chomp('.') if hostname.include?(url_host) + end + '' + end + + # Include user domain in lograge logs + def append_info_to_payload(payload) + super + payload[:host] = @user_domain + end + + # Manually Handle BigBlueButton errors + def handle_bigbluebutton_error + render "errors/bigbluebutton_error" end # Manually deal with 401 errors @@ -140,50 +197,6 @@ class ApplicationController < ActionController::Base render "errors/greenlight_error" end - # Checks to make sure that the admin has changed his password from the default - def check_admin_password - if current_user&.has_role?(:admin) && current_user.email == "admin@example.com" && - current_user&.greenlight_account? && current_user&.authenticate(Rails.configuration.admin_password_default) - - flash.now[:alert] = I18n.t("default_admin", - edit_link: edit_user_path(user_uid: current_user.uid) + "?setting=password").html_safe - end - end - - def redirect_to_https - if Rails.configuration.loadbalanced_configuration && request.headers["X-Forwarded-Proto"] == "http" - redirect_to protocol: "https://" - end - end - - def set_user_domain - if Rails.env.test? || !Rails.configuration.loadbalanced_configuration - @user_domain = "greenlight" - else - @user_domain = parse_user_domain(request.host) - - check_provider_exists - end - end - helper_method :set_user_domain - - # Checks if the user is banned and logs him out if he is - def check_user_role - if current_user&.has_role? :denied - session.delete(:user_id) - redirect_to root_path, flash: { alert: I18n.t("registration.banned.fail") } - elsif current_user&.has_role? :pending - session.delete(:user_id) - redirect_to root_path, flash: { alert: I18n.t("registration.approval.fail") } - end - end - helper_method :check_user_role - - # Manually Handle BigBlueButton errors - def handle_bigbluebutton_error - render "errors/bigbluebutton_error" - end - private def check_provider_exists @@ -198,6 +211,7 @@ class ApplicationController < ActionController::Base # Add a session variable if the provider exists session[:provider_exists] = @user_domain rescue => e + logger.error "Error in retrieve provider info: #{e}" # Use the default site settings @user_domain = "greenlight" diff --git a/app/helpers/sessions_helper.rb b/app/controllers/concerns/authenticator.rb similarity index 54% rename from app/helpers/sessions_helper.rb rename to app/controllers/concerns/authenticator.rb index e0183be6..e4ba2c04 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/controllers/concerns/authenticator.rb @@ -16,15 +16,15 @@ # You should have received a copy of the GNU Lesser General Public License along # with BigBlueButton; if not, see . -module SessionsHelper +module Authenticator + extend ActiveSupport::Concern + # Logs a user into GreenLight. def login(user) migrate_twitter_user(user) session[:user_id] = user.id - logger.info("Support: #{user.email} has successfully logged in.") - # If there are not terms, or the user has accepted them, check for email verification if !Rails.configuration.terms || user.accepted_terms check_email_verified(user) @@ -61,69 +61,9 @@ module SessionsHelper session.delete(:user_id) if current_user end - # Retrieves the current user. - def current_user - @current_user ||= User.where(id: session[:user_id]).includes(:roles).first - - if Rails.configuration.loadbalanced_configuration - if @current_user && !@current_user.has_role?(:super_admin) && - @current_user.provider != @user_domain - @current_user = nil - session.clear - end - end - - @current_user - end - - def generate_checksum(user_domain, redirect_url, secret) - string = user_domain + redirect_url + secret - OpenSSL::Digest.digest('sha1', string).unpack1("H*") - end - - def parse_user_domain(hostname) - return hostname.split('.').first if Rails.configuration.url_host.empty? - Rails.configuration.url_host.split(',').each do |url_host| - return hostname.chomp(url_host).chomp('.') if hostname.include?(url_host) - end - '' - end - - def omniauth_options(env) - if env['omniauth.strategy'].options[:name] == "bn_launcher" - protocol = Rails.env.production? ? "https" : env["rack.url_scheme"] - - customer_redirect_url = protocol + "://" + env["SERVER_NAME"] + ":" + - env["SERVER_PORT"] - user_domain = parse_user_domain(env["SERVER_NAME"]) - env['omniauth.strategy'].options[:customer] = user_domain - env['omniauth.strategy'].options[:customer_redirect_url] = customer_redirect_url - env['omniauth.strategy'].options[:default_callback_url] = Rails.configuration.gl_callback_url - - # This is only used in the old launcher and should eventually be removed - env['omniauth.strategy'].options[:checksum] = generate_checksum(user_domain, customer_redirect_url, - Rails.configuration.launcher_secret) - elsif env['omniauth.strategy'].options[:name] == "google" - set_hd(env, ENV['GOOGLE_OAUTH2_HD']) - elsif env['omniauth.strategy'].options[:name] == "office365" - set_hd(env, ENV['OFFICE365_HD']) - end - end - - def set_hd(env, hd) - if hd - hd_opts = hd.split(',') - env['omniauth.strategy'].options[:hd] = - if hd_opts.empty? - nil - elsif hd_opts.length == 1 - hd_opts[0] - else - hd_opts - end - end - end + private + # Migrates all of the twitter users rooms to the new account def migrate_twitter_user(user) if !session["old_twitter_user_id"].nil? && user.provider != "twitter" old_user = User.find(session["old_twitter_user_id"]) diff --git a/app/controllers/concerns/bbb_server.rb b/app/controllers/concerns/bbb_server.rb new file mode 100644 index 00000000..02b3fde7 --- /dev/null +++ b/app/controllers/concerns/bbb_server.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +require 'bigbluebutton_api' + +module BbbServer + extend ActiveSupport::Concern + include BbbApi + + META_LISTED = "gl-listed" + + # Checks if a room is running on the BigBlueButton server. + def room_running?(bbb_id) + bbb_server.is_meeting_running?(bbb_id) + end + + def get_recordings(meeting_id) + bbb_server.get_recordings(meetingID: meeting_id) + end + + def get_multiple_recordings(meeting_ids) + bbb_server.get_recordings(meetingID: meeting_ids) + end + + # Returns a URL to join a user into a meeting. + def join_path(room, name, options = {}, uid = nil) + # Create the meeting, even if it's running + start_session(room, options) + + # Determine the password to use when joining. + password = options[:user_is_moderator] ? room.moderator_pw : room.attendee_pw + + # Generate the join URL. + join_opts = {} + join_opts[:userID] = uid if uid + join_opts[:join_via_html5] = true + join_opts[:guest] = true if options[:require_moderator_approval] && !options[:user_is_moderator] + + bbb_server.join_meeting_url(room.bbb_id, name, password, join_opts) + end + + # Creates a meeting on the BigBlueButton server. + def start_session(room, options = {}) + create_options = { + record: options[:meeting_recorded].to_s, + logoutURL: options[:meeting_logout_url] || '', + moderatorPW: room.moderator_pw, + attendeePW: room.attendee_pw, + moderatorOnlyMessage: options[:moderator_message], + muteOnStart: options[:mute_on_start] || false, + "meta_#{META_LISTED}": options[:recording_default_visibility] || false, + "meta_bbb-origin-version": Greenlight::Application::VERSION, + "meta_bbb-origin": "Greenlight", + "meta_bbb-origin-server-name": options[:host] + } + + create_options[:guestPolicy] = "ASK_MODERATOR" if options[:require_moderator_approval] + + # Send the create request. + begin + meeting = bbb_server.create_meeting(room.name, room.bbb_id, create_options) + # Update session info. + unless meeting[:messageKey] == 'duplicateWarning' + room.update_attributes(sessions: room.sessions + 1, + last_session: DateTime.now) + end + rescue BigBlueButton::BigBlueButtonException => e + puts "BigBlueButton failed on create: #{e.key}: #{e.message}" + raise e + end + end + + # Gets the number of recordings for this room + def recording_count(bbb_id) + bbb_server.get_recordings(meetingID: bbb_id)[:recordings].length + end + + # Update a recording from a room + def update_recording(record_id, meta) + meta[:recordID] = record_id + bbb_server.send_api_request("updateRecordings", meta) + end + + # Deletes a recording from a room. + def delete_recording(record_id) + bbb_server.delete_recordings(record_id) + end + + # Deletes all recordings associated with the room. + def delete_all_recordings(bbb_id) + record_ids = bbb_server.get_recordings(meetingID: bbb_id)[:recordings].pluck(:recordID) + bbb_server.delete_recordings(record_ids) unless record_ids.empty? + end +end diff --git a/app/controllers/concerns/emailer.rb b/app/controllers/concerns/emailer.rb index 9146bb00..378ad62e 100644 --- a/app/controllers/concerns/emailer.rb +++ b/app/controllers/concerns/emailer.rb @@ -21,69 +21,110 @@ module Emailer # Sends account activation email. def send_activation_email(user) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - @user = user - UserMailer.verify_email(@user, user_verification_link, logo_image, user_color).deliver + UserMailer.verify_email(user, user_verification_link(user), @settings).deliver + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + else + flash[:success] = I18n.t("email_sent", email_type: t("verify.verification")) + end end # Sends password reset email. def send_password_reset_email(user) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - @user = user - UserMailer.password_reset(@user, reset_link, logo_image, user_color).deliver_now + UserMailer.password_reset(user, reset_link(user), @settings).deliver_now + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + else + flash[:success] = I18n.t("email_sent", email_type: t("reset_password.subtitle")) + end end def send_user_promoted_email(user, role) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - UserMailer.user_promoted(user, role, root_url, logo_image, user_color).deliver_now + UserMailer.user_promoted(user, role, root_url, @settings).deliver_now + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + end end def send_user_demoted_email(user, role) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - UserMailer.user_demoted(user, role, root_url, logo_image, user_color).deliver_now + UserMailer.user_demoted(user, role, root_url, @settings).deliver_now + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + end end # Sends inivitation to join def send_invitation_email(name, email, token) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - @token = token - UserMailer.invite_email(name, email, invitation_link, logo_image, user_color).deliver_now + UserMailer.invite_email(name, email, invitation_link(token), @settings).deliver_now + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + else + flash[:success] = I18n.t("administrator.flash.invite", email: email) + end end def send_user_approved_email(user) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - UserMailer.approve_user(user, root_url, logo_image, user_color).deliver_now + UserMailer.approve_user(user, root_url, @settings).deliver_now + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + else + flash[:success] = I18n.t("email_sent", email_type: t("verify.verification")) + end end def send_approval_user_signup_email(user) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - admin_emails = admin_emails() - unless admin_emails.empty? - UserMailer.approval_user_signup(user, admins_url, logo_image, user_color, admin_emails).deliver_now + admin_emails = admin_emails() + UserMailer.approval_user_signup(user, admins_url, admin_emails, @settings).deliver_now unless admin_emails.empty? + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) end end def send_invite_user_signup_email(user) - return unless Rails.configuration.enable_email_verification + begin + return unless Rails.configuration.enable_email_verification - admin_emails = admin_emails() - unless admin_emails.empty? - UserMailer.invite_user_signup(user, admins_url, logo_image, user_color, admin_emails).deliver_now + admin_emails = admin_emails() + UserMailer.invite_user_signup(user, admins_url, admin_emails, @settings).deliver_now unless admin_emails.empty? + rescue => e + logger.error "Support: Error in email delivery: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) end end private # Returns the link the user needs to click to verify their account - def user_verification_link - edit_account_activation_url(token: @user.activation_token, email: @user.email) + def user_verification_link(user) + edit_account_activation_url(token: user.activation_token, email: user.email) end def admin_emails @@ -91,21 +132,21 @@ module Emailer if Rails.configuration.loadbalanced_configuration admins = admins.without_role(:super_admin) - .where(provider: user_settings_provider) + .where(provider: @user_domain) end admins.collect(&:email).join(",") end - def reset_link - edit_password_reset_url(@user.reset_token, email: @user.email) + def reset_link(user) + edit_password_reset_url(user.reset_token, email: user.email) end - def invitation_link - if allow_greenlight_users? - signup_url(invite_token: @token) + def invitation_link(token) + if allow_greenlight_accounts? + signup_url(invite_token: token) else - root_url(invite_token: @token) + root_url(invite_token: token) end end end diff --git a/app/controllers/concerns/recorder.rb b/app/controllers/concerns/recorder.rb index 53e777e4..30a2dff2 100644 --- a/app/controllers/concerns/recorder.rb +++ b/app/controllers/concerns/recorder.rb @@ -18,29 +18,29 @@ module Recorder extend ActiveSupport::Concern - include ::BbbApi + include RecordingsHelper # Fetches all recordings for a room. - def recordings(room_bbb_id, provider, search_params = {}, ret_search_params = false) - res = bbb(provider).get_recordings(meetingID: room_bbb_id) + def recordings(room_bbb_id, search_params = {}, ret_search_params = false) + res = get_recordings(room_bbb_id) format_recordings(res, search_params, ret_search_params) end # Fetches a rooms public recordings. - def public_recordings(room_bbb_id, provider, search_params = {}, ret_search_params = false) - search, order_col, order_dir, recs = recordings(room_bbb_id, provider, search_params, ret_search_params) + def public_recordings(room_bbb_id, search_params = {}, ret_search_params = false) + search, order_col, order_dir, recs = recordings(room_bbb_id, search_params, ret_search_params) [search, order_col, order_dir, recs.select { |r| r[:metadata][:"gl-listed"] == "true" }] end # Makes paginated API calls to get recordings - def all_recordings(room_bbb_ids, provider, search_params = {}, ret_search_params = false, search_name = false) + def all_recordings(room_bbb_ids, search_params = {}, ret_search_params = false, search_name = false) res = { recordings: [] } until room_bbb_ids.empty? # bbb.get_recordings returns an object # take only the array portion of the object that is returned - full_res = bbb(provider).get_recordings(meetingID: room_bbb_ids.pop(Rails.configuration.pagination_number)) + full_res = get_multiple_recordings(room_bbb_ids.pop(Rails.configuration.pagination_number)) res[:recordings].push(*full_res[:recordings]) end diff --git a/app/controllers/concerns/registrar.rb b/app/controllers/concerns/registrar.rb index 79c0a622..34a77286 100644 --- a/app/controllers/concerns/registrar.rb +++ b/app/controllers/concerns/registrar.rb @@ -19,20 +19,12 @@ module Registrar extend ActiveSupport::Concern - def registration_method - Setting.find_or_create_by!(provider: user_settings_provider).get_value("Registration Method") - end - - def open_registration - registration_method == Rails.configuration.registration_methods[:open] - end - def approval_registration - registration_method == Rails.configuration.registration_methods[:approval] + @settings.get_value("Registration Method") == Rails.configuration.registration_methods[:approval] end def invite_registration - registration_method == Rails.configuration.registration_methods[:invite] + @settings.get_value("Registration Method") == Rails.configuration.registration_methods[:invite] end # Returns a hash containing whether the user has been invited and if they diff --git a/app/controllers/concerns/rolify.rb b/app/controllers/concerns/rolify.rb new file mode 100644 index 00000000..589a6d49 --- /dev/null +++ b/app/controllers/concerns/rolify.rb @@ -0,0 +1,161 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +module Rolify + extend ActiveSupport::Concern + + # Gets all roles + def all_roles(selected_role) + @roles = Role.editable_roles(@user_domain) + + if @roles.count.zero? + Role.create_default_roles(@user_domain) + @roles = Role.editable_roles(@user_domain) + end + + @selected_role = if selected_role.nil? + @roles.find_by(name: 'user') + else + @roles.find(selected_role) + end + + @roles + end + + # Creates a new role + def create_role(new_role_name) + # Make sure that the role name isn't a duplicate or a reserved name like super_admin or empty + return nil if Role.duplicate_name(new_role_name, @user_domain) || new_role_name.strip.empty? + + Role.create_new_role(new_role_name, @user_domain) + end + + # Updates a user's roles + def update_roles(roles) + # Check that the user can manage users + return true unless current_user.highest_priority_role.can_manage_users + + new_roles = roles.split(' ').map(&:to_i) + old_roles = @user.roles.pluck(:id) + + added_role_ids = new_roles - old_roles + removed_role_ids = old_roles - new_roles + + added_roles = [] + removed_roles = [] + current_user_role = current_user.highest_priority_role + + # Check that the user has the permissions to add all the new roles + added_role_ids.each do |id| + role = Role.find(id) + + # Admins are able to add the admin role to other users. All other roles may only + # add roles with a higher priority + if (role.priority > current_user_role.priority || current_user_role.name == "admin") && + role.provider == @user_domain + added_roles << role + else + return false + end + end + + # Check that the user has the permissions to remove all the deleted roles + removed_role_ids.each do |id| + role = Role.find(id) + + # Admins are able to remove the admin role from other users. All other roles may only + # remove roles with a higher priority + if (role.priority > current_user_role.priority || current_user_role.name == "admin") && + role.provider == @user_domain + removed_roles << role + else + return false + end + end + + # Send promoted/demoted emails + added_roles.each { |role| send_user_promoted_email(@user, role) if role.send_promoted_email } + removed_roles.each { |role| send_user_demoted_email(@user, role) if role.send_demoted_email } + + # Update the roles + @user.roles.delete(removed_roles) + @user.roles << added_roles + + # Make sure each user always has at least the user role + @user.roles = [Role.find_by(name: "user", provider: @user_domain)] if @user.roles.count.zero? + + @user.save! + end + + # Updates a roles priority + def update_priority(role_to_update) + user_role = Role.find_by(name: "user", provider: @user_domain) + admin_role = Role.find_by(name: "admin", provider: @user_domain) + + current_user_role = current_user.highest_priority_role + + # Users aren't allowed to update the priority of the admin or user roles + return false if role_to_update.include?(user_role.id.to_s) || role_to_update.include?(admin_role.id.to_s) + + # Restrict users to only updating the priority for roles in their domain with a higher + # priority + role_to_update.each do |id| + role = Role.find(id) + return false if role.priority <= current_user_role.priority || role.provider != @user_domain + end + + # Update the roles priority including the user role + top_priority = 0 + + role_to_update.each_with_index do |id, index| + new_priority = index + [current_user_role.priority, 0].max + 1 + top_priority = new_priority + Role.where(id: id).update_all(priority: new_priority) + end + + user_role.priority = top_priority + 1 + user_role.save! + end + + # Update Permissions + def update_permissions(role) + current_user_role = current_user.highest_priority_role + + # Checks that it is valid for the provider to update the role + return false if role.priority <= current_user_role.priority || role.provider != @user_domain + + role_params = params.require(:role).permit(:name) + permission_params = params.require(:role).permit(:can_create_rooms, :send_promoted_email, + :send_demoted_email, :can_edit_site_settings, :can_edit_roles, :can_manage_users, :colour) + + # Role is a default role so users can't change the name + role_params[:name] = role.name if Role::RESERVED_ROLE_NAMES.include?(role.name) + + # Make sure if the user is updating the role name that the role name is valid + if role.name != role_params[:name] && !Role.duplicate_name(role_params[:name], @user_domain) && + !role_params[:name].strip.empty? + role.name = role_params[:name] + elsif role.name != role_params[:name] + return false + end + + role.update(permission_params) + + role.save! + end +end diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb index 84ccb389..9c77194b 100644 --- a/app/controllers/password_resets_controller.rb +++ b/app/controllers/password_resets_controller.rb @@ -20,45 +20,47 @@ class PasswordResetsController < ApplicationController include Emailer before_action :disable_password_reset, unless: -> { Rails.configuration.enable_email_verification } - before_action :find_user, only: [:edit, :update] + before_action :find_user, only: [:edit, :update] before_action :valid_user, only: [:edit, :update] before_action :check_expiration, only: [:edit, :update] - def index + # POST /password_resets/new + def new end + # POST /password_resets def create - @user = User.find_by(email: params[:password_reset][:email].downcase) - if @user + begin + # Check if user exists and throw an error if he doesn't + @user = User.find_by!(email: params[:password_reset][:email].downcase) + @user.create_reset_digest send_password_reset_email(@user) - flash[:success] = I18n.t("email_sent", email_type: t("reset_password.subtitle")) redirect_to root_path - else - flash[:alert] = I18n.t("no_user_email_exists") - redirect_to new_password_reset_path + rescue + # User doesn't exist + redirect_to new_password_reset_path, flash: { alert: I18n.t("no_user_email_exists") } end - rescue => e - logger.error "Support: Error in email delivery: #{e}" - redirect_to root_path, alert: I18n.t(params[:message], default: I18n.t("delivery_error")) end + # GET /password_resets/:id/edit def edit end + # PATCH /password_resets/:id def update + # Check if password is valid if params[:user][:password].empty? flash.now[:alert] = I18n.t("password_empty_notice") - render 'edit' elsif params[:user][:password] != params[:user][:password_confirmation] + # Password does not match password confirmation flash.now[:alert] = I18n.t("password_different_notice") - render 'edit' elsif @user.update_attributes(user_params) - flash[:success] = I18n.t("password_reset_success") - redirect_to root_path - else - render 'edit' + # Successfully reset password + return redirect_to root_path, flash: { success: I18n.t("password_reset_success") } end + + render 'edit' end private @@ -84,6 +86,7 @@ class PasswordResetsController < ApplicationController end end + # Redirects to 404 if emails are not enabled def disable_password_reset redirect_to '/404' end diff --git a/app/controllers/recordings_controller.rb b/app/controllers/recordings_controller.rb index ad1c2806..d9e7f9e8 100644 --- a/app/controllers/recordings_controller.rb +++ b/app/controllers/recordings_controller.rb @@ -23,23 +23,23 @@ class RecordingsController < ApplicationController META_LISTED = "gl-listed" # POST /:meetingID/:record_id - def update_recording + def update meta = { "meta_#{META_LISTED}" => (params[:state] == "public"), } - res = @room.update_recording(params[:record_id], meta) + res = update_recording(params[:record_id], meta) # Redirects to the page that made the initial request - redirect_to request.referrer if res[:updated] + redirect_back fallback_location: root_path if res[:updated] end # DELETE /:meetingID/:record_id - def delete_recording - @room.delete_recording(params[:record_id]) + def delete + delete_recording(params[:record_id]) # Redirects to the page that made the initial request - redirect_to request.referrer + redirect_back fallback_location: root_path end private diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 4771d7de..1aee8f00 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -17,7 +17,6 @@ # with BigBlueButton; if not, see . class RoomsController < ApplicationController - include RecordingsHelper include Pagy::Backend include Recorder @@ -32,42 +31,47 @@ class RoomsController < ApplicationController # POST / def create - redirect_to(root_path) && return unless current_user + # Return to root if user is not signed in + return redirect_to root_path unless current_user + # Check if the user has not exceeded the room limit return redirect_to current_user.main_room, flash: { alert: I18n.t("room.room_limit") } if room_limit_exceeded + # Create room @room = Room.new(name: room_params[:name], access_code: room_params[:access_code]) @room.owner = current_user - @room.room_settings = create_room_settings_string(room_params[:mute_on_join], - room_params[:require_moderator_approval], room_params[:anyone_can_start], room_params[:all_join_moderator]) + @room.room_settings = create_room_settings_string(room_params) + # Save the room if @room.save - logger.info("Support: #{current_user.email} has created a new room #{@room.uid}.") + logger.info "Support: #{current_user.email} has created a new room #{@room.uid}." + # Start the room if auto join was turned on if room_params[:auto_join] == "1" start else - flash[:success] = I18n.t("room.create_room_success") - redirect_to @room + redirect_to @room, flash: { success: I18n.t("room.create_room_success") } end else - flash[:alert] = I18n.t("room.create_room_error") - redirect_to current_user.main_room + redirect_to current_user.main_room, flash: { alert: I18n.t("room.create_room_error") } end end # GET /:room_uid def show - @is_running = @room.running? @anyone_can_start = JSON.parse(@room[:room_settings])["anyoneCanStart"] + @room_running = room_running?(@room.bbb_id) + # If its the current user's room if current_user && @room.owned_by?(current_user) if current_user.highest_priority_role.can_create_rooms + # User is allowed to have rooms @search, @order_column, @order_direction, recs = - recordings(@room.bbb_id, @user_domain, params.permit(:search, :column, :direction), true) + recordings(@room.bbb_id, params.permit(:search, :column, :direction), true) @pagy, @recordings = pagy_array(recs) else + # Render view for users that cant create rooms @recent_rooms = Room.where(id: cookies.encrypted["#{current_user.uid}_recently_joined_rooms"]) render :cant_create_rooms end @@ -84,7 +88,7 @@ class RoomsController < ApplicationController end @search, @order_column, @order_direction, pub_recs = - public_recordings(@room.bbb_id, @user_domain, params.permit(:search, :column, :direction), true) + public_recordings(@room.bbb_id, params.permit(:search, :column, :direction), true) @pagy, @public_recordings = pagy_array(pub_recs) @@ -94,20 +98,13 @@ class RoomsController < ApplicationController # PATCH /:room_uid def update - if params[:setting] == "rename_block" - @room = Room.find_by!(uid: params[:room_block_uid]) - update_room_attributes("name") - elsif params[:setting] == "rename_header" + if params[:setting] == "rename_header" update_room_attributes("name") elsif params[:setting] == "rename_recording" - @room.update_recording(params[:record_id], "meta_name" => params[:record_name]) + update_recording(params[:record_id], "meta_name" => params[:record_name]) end - if request.referrer - redirect_to request.referrer - else - redirect_to room_path - end + redirect_back fallback_location: room_path end # POST /:room_uid @@ -115,10 +112,8 @@ class RoomsController < ApplicationController return redirect_to root_path, flash: { alert: I18n.t("administrator.site_settings.authentication.user-info") } if auth_required - opts = default_meeting_options unless @room.owned_by?(current_user) - # Don't allow users to join unless they have a valid access code or the room doesn't - # have an access code + # Don't allow users to join unless they have a valid access code or the room doesn't have an access code if @room.access_code && !@room.access_code.empty? && @room.access_code != session[:access_code] return redirect_to room_path(room_uid: params[:room_uid]), flash: { alert: I18n.t("room.access_code_required") } end @@ -138,41 +133,41 @@ class RoomsController < ApplicationController if current_user # create or update cookie to track the three most recent rooms a user joined recently_joined_rooms = cookies.encrypted["#{current_user.uid}_recently_joined_rooms"].to_a - cookies.encrypted["#{current_user.uid}_recently_joined_rooms"] = recently_joined_rooms.prepend(@room.id) - .uniq[0..2] + cookies.encrypted["#{current_user.uid}_recently_joined_rooms"] = + recently_joined_rooms.prepend(@room.id).uniq[0..2] end - logger.info("Support: #{current_user.present? ? current_user.email : @join_name} is joining room #{@room.uid}") - - join_room(opts) + logger.info "Support: #{current_user.present? ? current_user.email : @join_name} is joining room #{@room.uid}" + join_room(default_meeting_options) end # DELETE /:room_uid def destroy # Don't delete the users home room. - @room.destroy if @room.owned_by?(current_user) && @room != current_user.main_room + if @room.owned_by?(current_user) && @room != current_user.main_room + @room.destroy + delete_all_recordings(@room.bbb_id) + end redirect_to current_user.main_room end - # POST room/join + # POST /room/join def join_specific_room room_uid = params[:join_room][:url].split('/').last begin - @room = Room.find_by(uid: room_uid) + @room = Room.find_by!(uid: room_uid) rescue ActiveRecord::RecordNotFound return redirect_to current_user.main_room, alert: I18n.t("room.no_room.invalid_room_uid") end - return redirect_to current_user.main_room, alert: I18n.t("room.no_room.invalid_room_uid") if @room.nil? - redirect_to room_path(@room) end # POST /:room_uid/start def start - logger.info("Support: #{current_user.email} is starting room #{@room.uid}") + logger.info "Support: #{current_user.email} is starting room #{@room.uid}" # Join the user in and start the meeting. opts = default_meeting_options @@ -184,7 +179,7 @@ class RoomsController < ApplicationController opts[:require_moderator_approval] = room_settings["requireModeratorApproval"] begin - redirect_to @room.join_path(current_user.name, opts, current_user.uid) + redirect_to join_path(@room, current_user.name, opts, current_user.uid) rescue BigBlueButton::BigBlueButtonException => e logger.error("Support: #{@room.uid} start failed: #{e}") @@ -208,7 +203,8 @@ class RoomsController < ApplicationController update_room_attributes("name") if @room.name != room_params[:name] # Update the room's access code if it has changed update_room_attributes("access_code") if @room.access_code != room_params[:access_code] - rescue StandardError + rescue => e + logger.error "Error in updating room settings: #{e}" flash[:alert] = I18n.t("room.update_settings_error") else flash[:success] = I18n.t("room.update_settings_success") @@ -218,7 +214,7 @@ class RoomsController < ApplicationController # GET /:room_uid/logout def logout - logger.info("Support: #{current_user.present? ? current_user.email : 'Guest'} has left room #{@room.uid}") + logger.info "Support: #{current_user.present? ? current_user.email : 'Guest'} has left room #{@room.uid}" # Redirect the correct page. redirect_to @room @@ -240,8 +236,7 @@ class RoomsController < ApplicationController if update_type.eql? "name" @room.update_attributes(name: params[:room_name] || room_params[:name]) elsif update_type.eql? "settings" - room_settings_string = create_room_settings_string(room_params[:mute_on_join], - room_params[:require_moderator_approval], room_params[:anyone_can_start], room_params[:all_join_moderator]) + room_settings_string = create_room_settings_string(room_params) @room.update_attributes(room_settings: room_settings_string) elsif update_type.eql? "access_code" @room.update_attributes(access_code: room_params[:access_code]) @@ -249,15 +244,15 @@ class RoomsController < ApplicationController end end - def create_room_settings_string(mute_res, require_approval_res, start_res, join_mod) + def create_room_settings_string(options) room_settings = {} - room_settings["muteOnStart"] = mute_res == "1" + room_settings["muteOnStart"] = options[:mute_on_join] == "1" - room_settings["requireModeratorApproval"] = require_approval_res == "1" + room_settings["requireModeratorApproval"] = options[:require_moderator_approval] == "1" - room_settings["anyoneCanStart"] = start_res == "1" + room_settings["anyoneCanStart"] = options[:anyone_can_start] == "1" - room_settings["joinModerator"] = join_mod == "1" + room_settings["joinModerator"] = options[:all_join_moderator] == "1" room_settings.to_json end @@ -289,15 +284,11 @@ class RoomsController < ApplicationController end def validate_accepted_terms - if current_user - redirect_to terms_path unless current_user.accepted_terms - end + redirect_to terms_path if current_user && !current_user&.accepted_terms end def validate_verified_email - if current_user - redirect_to account_activation_path(current_user) unless current_user.activated? - end + redirect_to account_activation_path(current_user) if current_user && !current_user&.activated? end def verify_room_owner_verified @@ -313,28 +304,28 @@ class RoomsController < ApplicationController end def verify_user_not_admin - redirect_to admins_path if current_user && current_user&.has_role?(:super_admin) + redirect_to admins_path if current_user&.has_role?(:super_admin) end def auth_required - Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Authentication") == "true" && - current_user.nil? + @settings.get_value("Room Authentication") == "true" && current_user.nil? end def room_limit_exceeded - limit = Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Limit").to_i + limit = @settings.get_value("Room Limit").to_i - # Does not apply to admin + # Does not apply to admin or users that aren't signed in # 15+ option is used as unlimited return false if current_user&.has_role?(:admin) || limit == 15 - current_user.rooms.count >= limit + current_user.rooms.length >= limit end + helper_method :room_limit_exceeded def join_room(opts) room_settings = JSON.parse(@room[:room_settings]) - if @room.running? || @room.owned_by?(current_user) || room_settings["anyoneCanStart"] + if room_running?(@room.bbb_id) || @room.owned_by?(current_user) || room_settings["anyoneCanStart"] # Determine if the user needs to join as a moderator. opts[:user_is_moderator] = @room.owned_by?(current_user) || room_settings["joinModerator"] @@ -342,15 +333,15 @@ class RoomsController < ApplicationController opts[:require_moderator_approval] = room_settings["requireModeratorApproval"] if current_user - redirect_to @room.join_path(current_user.name, opts, current_user.uid) + redirect_to join_path(@room, current_user.name, opts, current_user.uid) else join_name = params[:join_name] || params[@room.invite_path][:join_name] - redirect_to @room.join_path(join_name, opts) + redirect_to join_path(@room, join_name, opts) end else search_params = params[@room.invite_path] || params @search, @order_column, @order_direction, pub_recs = - public_recordings(@room.bbb_id, @user_domain, search_params.permit(:search, :column, :direction), true) + public_recordings(@room.bbb_id, search_params.permit(:search, :column, :direction), true) @pagy, @public_recordings = pagy_array(pub_recs) @@ -362,4 +353,17 @@ class RoomsController < ApplicationController def incorrect_user_domain Rails.configuration.loadbalanced_configuration && @room.owner.provider != @user_domain end + + # Default, unconfigured meeting options. + def default_meeting_options + invite_msg = I18n.t("invite_message") + { + user_is_moderator: false, + meeting_logout_url: request.base_url + logout_room_path(@room), + meeting_recorded: true, + moderator_message: "#{invite_msg}\n\n#{request.base_url + room_path(@room)}", + host: request.host, + recording_default_visibility: @settings.get_value("Default Recording Visibility") == "public" + } + end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index cde24e24..22c7f396 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -17,21 +17,16 @@ # with BigBlueButton; if not, see . class SessionsController < ApplicationController + include Authenticator include Registrar include Emailer include LdapAuthenticator skip_before_action :verify_authenticity_token, only: [:omniauth, :fail] - # GET /users/logout - def destroy - logout - redirect_to root_path - end - # POST /users/login def create - logger.info("Support: #{session_params[:email]} is attempting to login.") + logger.info "Support: #{session_params[:email]} is attempting to login." admin = User.find_by(email: session_params[:email]) if admin&.has_role? :super_admin @@ -48,11 +43,22 @@ class SessionsController < ApplicationController login(user) end + # GET /users/logout + def destroy + logout + redirect_to root_path + end + # GET/POST /auth/:provider/callback def omniauth @auth = request.env['omniauth.auth'] - process_signin + begin + process_signin + rescue => e + logger.error "Error authenticating via omniauth: #{e}" + omniauth_fail + end end # POST /auth/failure @@ -81,15 +87,16 @@ class SessionsController < ApplicationController result = send_ldap_request(params[:session], ldap_config) - if result - result = result.first - else - return redirect_to(ldap_signin_path, alert: I18n.t("invalid_credentials")) + return redirect_to(ldap_signin_path, alert: I18n.t("invalid_credentials")) unless result + + @auth = parse_auth(result.first, ENV['LDAP_ROLE_FIELD']) + + begin + process_signin + rescue => e + logger.error "Support: Error authenticating via omniauth: #{e}" + omniauth_fail end - - @auth = parse_auth(result, ENV['LDAP_ROLE_FIELD']) - - process_signin end private @@ -112,47 +119,39 @@ class SessionsController < ApplicationController end def process_signin - begin - @user_exists = check_user_exists + @user_exists = check_user_exists - if !@user_exists && @auth['provider'] == "twitter" - return redirect_to root_path, flash: { alert: I18n.t("registration.deprecated.twitter_signup") } + if !@user_exists && @auth['provider'] == "twitter" + return redirect_to root_path, flash: { alert: I18n.t("registration.deprecated.twitter_signup") } + end + + # If using invitation registration method, make sure user is invited + return redirect_to root_path, flash: { alert: I18n.t("registration.invite.no_invite") } unless passes_invite_reqs + + user = User.from_omniauth(@auth) + + logger.info "Support: Auth user #{user.email} is attempting to login." + + # Add pending role if approval method and is a new user + if approval_registration && !@user_exists + user.add_role :pending + + # Inform admins that a user signed up if emails are turned on + send_approval_user_signup_email(user) + + return redirect_to root_path, flash: { success: I18n.t("registration.approval.signup") } + end + + send_invite_user_signup_email(user) if invite_registration && !@user_exists + + login(user) + + if @auth['provider'] == "twitter" + flash[:alert] = if allow_user_signup? && allow_greenlight_accounts? + I18n.t("registration.deprecated.twitter_signin", link: signup_path(old_twitter_user_id: user.id)) + else + I18n.t("registration.deprecated.twitter_signin", link: signin_path(old_twitter_user_id: user.id)) end - - # If using invitation registration method, make sure user is invited - return redirect_to root_path, flash: { alert: I18n.t("registration.invite.no_invite") } unless passes_invite_reqs - - user = User.from_omniauth(@auth) - - logger.info("Support: Auth user #{user.email} is attempting to login.") - - # Add pending role if approval method and is a new user - if approval_registration && !@user_exists - user.add_role :pending - - # Inform admins that a user signed up if emails are turned on - send_approval_user_signup_email(user) if Rails.configuration.enable_email_verification - - return redirect_to root_path, flash: { success: I18n.t("registration.approval.signup") } - end - - send_invite_user_signup_email(user) if Rails.configuration.enable_email_verification && - invite_registration && !@user_exists - - login(user) - - if @auth['provider'] == "twitter" - flash[:alert] = if allow_user_signup? && allow_greenlight_accounts? - I18n.t("registration.deprecated.twitter_signin", - link: signup_path(old_twitter_user_id: user.id)) - else - I18n.t("registration.deprecated.twitter_signin", - link: signin_path(old_twitter_user_id: user.id)) - end - end - rescue => e - logger.error "Support: Error authenticating via omniauth: #{e}" - omniauth_fail end end end diff --git a/app/controllers/themes_controller.rb b/app/controllers/themes_controller.rb index d10521ca..bfbfeb56 100644 --- a/app/controllers/themes_controller.rb +++ b/app/controllers/themes_controller.rb @@ -18,7 +18,6 @@ class ThemesController < ApplicationController skip_before_action :maintenance_mode? - before_action :provider_settings # GET /primary def index @@ -39,10 +38,4 @@ class ThemesController < ApplicationController format.css { render body: @compiled } end end - - private - - def provider_settings - @settings = Setting.find_or_create_by(provider: user_settings_provider) - end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 527c381a..a38f85fb 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -17,14 +17,16 @@ # with BigBlueButton; if not, see . class UsersController < ApplicationController - include RecordingsHelper include Pagy::Backend + include Authenticator include Emailer include Registrar include Recorder + include Rolify - before_action :find_user, only: [:edit, :update, :destroy] + before_action :find_user, only: [:edit, :change_password, :delete_account, :update, :destroy] before_action :ensure_unauthenticated, only: [:new, :create, :signin] + before_action :check_admin_of, only: [:edit, :change_password, :delete_account] # POST /u def create @@ -43,7 +45,7 @@ class UsersController < ApplicationController # User has passed all validations required @user.save - logger.info("Support: #{@user.email} user has been created.") + logger.info "Support: #{@user.email} user has been created." # Set user to pending and redirect if Approval Registration is set if approval_registration @@ -53,12 +55,12 @@ class UsersController < ApplicationController flash: { success: I18n.t("registration.approval.signup") } unless Rails.configuration.enable_email_verification end - send_registration_email if Rails.configuration.enable_email_verification + send_registration_email # Sign in automatically if email verification is disabled or if user is already verified. login(@user) && return if !Rails.configuration.enable_email_verification || @user.email_verified - send_verification + send_activation_email(@user) redirect_to root_path end @@ -109,11 +111,15 @@ class UsersController < ApplicationController # GET /u/:user_uid/edit def edit - if current_user - redirect_to current_user.main_room if @user != current_user && !current_user.admin_of?(@user) - else - redirect_to root_path - end + redirect_to root_path unless current_user + end + + # GET /u/:user_uid/change_password + def change_password + end + + # GET /u/:user_uid/delete_account + def delete_account end # PATCH /u/:user_uid/edit @@ -139,31 +145,32 @@ class UsersController < ApplicationController if errors.empty? && @user.save # Notify the user that their account has been updated. - flash[:success] = I18n.t("info_update_success") - redirect_to redirect_path + redirect_to redirect_path, flash: { success: I18n.t("info_update_success") } else # Append custom errors. errors.each { |k, v| @user.errors.add(k, v) } render :edit, params: { settings: params[:settings] } end - elsif user_params[:email] != @user.email && @user.update_attributes(user_params) && update_roles - @user.update_attributes(email_verified: false) - - flash[:success] = I18n.t("info_update_success") - redirect_to redirect_path - elsif @user.update_attributes(user_params) && update_roles - update_locale(@user) - - flash[:success] = I18n.t("info_update_success") - redirect_to redirect_path else + if @user.update_attributes(user_params) + @user.update_attributes(email_verified: false) if user_params[:email] != @user.email + + user_locale(@user) + + if update_roles(params[:user][:role_ids]) + return redirect_to redirect_path, flash: { success: I18n.t("info_update_success") } + else + flash[:alert] = I18n.t("administrator.roles.invalid_assignment") + end + end + render :edit, params: { settings: params[:settings] } end end # DELETE /u/:user_uid def destroy - logger.info("Support: #{current_user.email} is deleting #{@user.email}.") + logger.info "Support: #{current_user.email} is deleting #{@user.email}." if current_user && current_user == @user @user.destroy @@ -186,8 +193,7 @@ class UsersController < ApplicationController def recordings if current_user && current_user.uid == params[:user_uid] @search, @order_column, @order_direction, recs = - all_recordings(current_user.rooms.pluck(:bbb_id), current_user.provider, - params.permit(:search, :column, :direction), true) + all_recordings(current_user.rooms.pluck(:bbb_id), params.permit(:search, :column, :direction), true) @pagy, @recordings = pagy_array(recs) else redirect_to root_path @@ -219,28 +225,11 @@ class UsersController < ApplicationController :new_password, :provider, :accepted_terms, :language) end - def send_verification - # Start email verification and redirect to root. - begin - send_activation_email(@user) - rescue => e - logger.error "Support: Error in email delivery: #{e}" - flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) - else - flash[:success] = I18n.t("email_sent", email_type: t("verify.verification")) - end - end - def send_registration_email - begin - if invite_registration - send_invite_user_signup_email(@user) - elsif approval_registration - send_approval_user_signup_email(@user) - end - rescue => e - logger.error "Support: Error in email delivery: #{e}" - flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error")) + if invite_registration + send_invite_user_signup_email(@user) + elsif approval_registration + send_approval_user_signup_email(@user) end end @@ -264,64 +253,8 @@ class UsersController < ApplicationController invitation[:present] end - # Updates as user's roles - def update_roles - # Check that the user can manage users - if current_user.highest_priority_role.can_manage_users - new_roles = params[:user][:role_ids].split(' ').map(&:to_i) - old_roles = @user.roles.pluck(:id) - - added_role_ids = new_roles - old_roles - removed_role_ids = old_roles - new_roles - - added_roles = [] - removed_roles = [] - current_user_role = current_user.highest_priority_role - - # Check that the user has the permissions to add all the new roles - added_role_ids.each do |id| - role = Role.find(id) - - # Admins are able to add the admin role to other users. All other roles may only - # add roles with a higher priority - if (role.priority > current_user_role.priority || current_user_role.name == "admin") && - role.provider == @user_domain - added_roles << role - else - flash[:alert] = I18n.t("administrator.roles.invalid_assignment") - return false - end - end - - # Check that the user has the permissions to remove all the deleted roles - removed_role_ids.each do |id| - role = Role.find(id) - - # Admins are able to remove the admin role from other users. All other roles may only - # remove roles with a higher priority - if (role.priority > current_user_role.priority || current_user_role.name == "admin") && - role.provider == @user_domain - removed_roles << role - else - flash[:alert] = I18n.t("administrator.roles.invalid_removal") - return false - end - end - - # Send promoted/demoted emails - added_roles.each { |role| send_user_promoted_email(@user, role) if role.send_promoted_email } - removed_roles.each { |role| send_user_demoted_email(@user, role) if role.send_demoted_email } - - # Update the roles - @user.roles.delete(removed_roles) - @user.roles << added_roles - - # Make sure each user always has at least the user role - @user.roles = [Role.find_by(name: "user", provider: @user_domain)] if @user.roles.count.zero? - - @user.save! - else - true - end + # Checks that the user is allowed to edit this user + def check_admin_of + redirect_to current_user.main_room if current_user && @user != current_user && !current_user.admin_of?(@user) end end diff --git a/app/helpers/account_activations_helper.rb b/app/helpers/account_activations_helper.rb deleted file mode 100644 index 4cddbd77..00000000 --- a/app/helpers/account_activations_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -module AccountActivationsHelper -end diff --git a/app/helpers/admins_helper.rb b/app/helpers/admins_helper.rb index c517c9f6..7dd762e6 100644 --- a/app/helpers/admins_helper.rb +++ b/app/helpers/admins_helper.rb @@ -19,36 +19,17 @@ module AdminsHelper include Pagy::Frontend - # Returns the action method of the current page - def active_page - route = Rails.application.routes.recognize_path(request.env['PATH_INFO']) - - route[:action] - end - # Gets the email of the room owner to which the recording belongs to def recording_owner_email(room_id) Room.find_by(bbb_id: room_id).owner.email end - def display_invite - current_page?(admins_path) && invite_registration - end - - def registration_method - Setting.find_or_create_by!(provider: user_settings_provider).get_value("Registration Method") - end - def invite_registration - registration_method == Rails.configuration.registration_methods[:invite] - end - - def approval_registration - registration_method == Rails.configuration.registration_methods[:approval] + @settings.get_value("Registration Method") == Rails.configuration.registration_methods[:invite] end def room_authentication_string - if Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Authentication") == "true" + if @settings.get_value("Room Authentication") == "true" I18n.t("administrator.site_settings.authentication.enabled") else I18n.t("administrator.site_settings.authentication.disabled") @@ -56,8 +37,7 @@ module AdminsHelper end def recording_default_visibility_string - if Setting.find_or_create_by!(provider: user_settings_provider) - .get_value("Default Recording Visibility") == "public" + if @settings.get_value("Default Recording Visibility") == "public" I18n.t("recording.visibility.public") else I18n.t("recording.visibility.unlisted") @@ -65,7 +45,7 @@ module AdminsHelper end def registration_method_string - case registration_method + case @settings.get_value("Registration Method") when Rails.configuration.registration_methods[:open] I18n.t("administrator.site_settings.registration.methods.open") when Rails.configuration.registration_methods[:invite] @@ -76,7 +56,7 @@ module AdminsHelper end def room_limit_number - Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Limit").to_i + @settings.get_value("Room Limit").to_i end def edit_disabled diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7ae53282..155335cf 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -18,20 +18,8 @@ require 'bbb_api' require 'uri' -require 'i18n/language/mapping' module ApplicationHelper - include MeetingsHelper - include BbbApi - include I18n::Language::Mapping - - # Gets all configured omniauth providers. - def configured_providers - Rails.configuration.providers.select do |provider| - Rails.configuration.send("omniauth_#{provider}") - end - end - # Determines which providers can show a login button in the login modal. def iconset_providers providers = configured_providers & [:google, :twitter, :office365, :ldap] @@ -50,53 +38,9 @@ module ApplicationHelper end end - # Determine if Greenlight is configured to allow user signups. - def allow_user_signup? - Rails.configuration.allow_user_signup - end - - # Determines if the BigBlueButton endpoint is the default. - def bigbluebutton_endpoint_default? - Rails.configuration.bigbluebutton_endpoint_default == Rails.configuration.bigbluebutton_endpoint - end - - # Returns language selection options - def language_options - locales = I18n.available_locales - language_opts = [['<<<< ' + t("language_default") + ' >>>>', "default"]] - locales.each do |locale| - language_mapping = I18n::Language::Mapping.language_mapping_list[locale.to_s.gsub("_", "-")] - language_opts.push([language_mapping["nativeName"], locale.to_s]) - end - language_opts.sort - end - - # Parses markdown for rendering. - def markdown(text) - markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, - no_intra_emphasis: true, - fenced_code_blocks: true, - disable_indented_code_blocks: true, - autolink: true, - tables: true, - underline: true, - highlight: true) - - markdown.render(text).html_safe - end - - def allow_greenlight_accounts? - return Rails.configuration.allow_user_signup unless Rails.configuration.loadbalanced_configuration - return false unless @user_domain && !@user_domain.empty? && Rails.configuration.allow_user_signup - return false if @user_domain == "greenlight" - # Proceed with retrieving the provider info - begin - provider_info = retrieve_provider_info(@user_domain, 'api2', 'getUserGreenlightCredentials') - provider_info['provider'] == 'greenlight' - rescue => e - logger.info e - false - end + # Determines if a form field needs the is-invalid class. + def form_is_invalid?(obj, key) + 'is-invalid' unless obj.errors.messages[key].empty? end # Return all the translations available in the client side through javascript @@ -118,6 +62,13 @@ module ApplicationHelper current_user.main_room end + # Returns the action method of the current page + def active_page + route = Rails.application.routes.recognize_path(request.env['PATH_INFO']) + + route[:action] + end + def role_colour(role) role.colour || Rails.configuration.primary_color_default end diff --git a/app/helpers/errors_helper.rb b/app/helpers/errors_helper.rb deleted file mode 100644 index 955cbf7a..00000000 --- a/app/helpers/errors_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -module ErrorsHelper -end diff --git a/app/helpers/main_helper.rb b/app/helpers/main_helper.rb deleted file mode 100644 index 2ae4ce75..00000000 --- a/app/helpers/main_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -module MainHelper -end diff --git a/app/helpers/meetings_helper.rb b/app/helpers/meetings_helper.rb deleted file mode 100644 index ca691815..00000000 --- a/app/helpers/meetings_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -module MeetingsHelper -end diff --git a/app/helpers/password_resets_helper.rb b/app/helpers/password_resets_helper.rb deleted file mode 100644 index bfc3d834..00000000 --- a/app/helpers/password_resets_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -module PasswordResetsHelper -end diff --git a/app/helpers/recordings_helper.rb b/app/helpers/recordings_helper.rb index 0ab14306..06296457 100644 --- a/app/helpers/recordings_helper.rb +++ b/app/helpers/recordings_helper.rb @@ -17,8 +17,6 @@ # with BigBlueButton; if not, see . module RecordingsHelper - include Pagy::Frontend - # Helper for converting BigBlueButton dates into the desired format. def recording_date(date) I18n.l date, format: "%B %d, %Y" @@ -48,4 +46,9 @@ module RecordingsHelper def room_uid_from_bbb(bbb_id) Room.find_by(bbb_id: bbb_id)[:uid] end + + # returns whether recording thumbnails are enabled on the server + def recording_thumbnails? + Rails.configuration.recording_thumbnails + end end diff --git a/app/helpers/rooms_helper.rb b/app/helpers/rooms_helper.rb index 009fd77d..d98f772f 100644 --- a/app/helpers/rooms_helper.rb +++ b/app/helpers/rooms_helper.rb @@ -24,27 +24,13 @@ module RoomsHelper end def room_authentication_required - Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Authentication") == "true" && + @settings.get_value("Room Authentication") == "true" && current_user.nil? end - def number_of_rooms_allowed - Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Limit").to_i - end - - def room_limit_exceeded - limit = Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Limit").to_i - - # Does not apply to admin or users that aren't signed in - # 15+ option is used as unlimited - return false if current_user&.has_role?(:admin) || limit == 15 - - current_user.rooms.length >= limit - end - def current_room_exceeds_limit(room) # Get how many rooms need to be deleted to reach allowed room number - limit = Setting.find_or_create_by!(provider: user_settings_provider).get_value("Room Limit").to_i + limit = @settings.get_value("Room Limit").to_i return false if current_user&.has_role?(:admin) || limit == 15 diff --git a/app/helpers/theming_helper.rb b/app/helpers/theming_helper.rb index e3f073fb..bb725f12 100644 --- a/app/helpers/theming_helper.rb +++ b/app/helpers/theming_helper.rb @@ -19,24 +19,11 @@ module ThemingHelper # Returns the logo based on user's provider def logo_image - Setting.find_or_create_by(provider: user_settings_provider) - .get_value("Branding Image") || Rails.configuration.branding_image_default + @settings.get_value("Branding Image") || Rails.configuration.branding_image_default end # Returns the primary color based on user's provider def user_color - Setting.find_or_create_by(provider: user_settings_provider) - .get_value("Primary Color") || Rails.configuration.primary_color_default - end - - # Returns the user's provider in the settings context - def user_settings_provider - if Rails.configuration.loadbalanced_configuration && current_user && !current_user&.has_role?(:super_admin) - current_user.provider - elsif Rails.configuration.loadbalanced_configuration - @user_domain - else - "greenlight" - end + @settings.get_value("Primary Color") || Rails.configuration.primary_color_default end end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index c62f3d7e..c92ce09b 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -16,7 +16,11 @@ # You should have received a copy of the GNU Lesser General Public License along # with BigBlueButton; if not, see . +require 'i18n/language/mapping' + module UsersHelper + include I18n::Language::Mapping + def recaptcha_enabled? Rails.configuration.recaptcha_enabled end @@ -36,4 +40,29 @@ module UsersHelper user.roles.by_priority.pluck(:id) | disallowed_roles end + + # Returns language selection options for user edit + def language_options + locales = I18n.available_locales + language_opts = [['<<<< ' + t("language_default") + ' >>>>', "default"]] + locales.each do |locale| + language_mapping = I18n::Language::Mapping.language_mapping_list[locale.to_s.gsub("_", "-")] + language_opts.push([language_mapping["nativeName"], locale.to_s]) + end + language_opts.sort + end + + # Parses markdown for rendering. + def markdown(text) + markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, + no_intra_emphasis: true, + fenced_code_blocks: true, + disable_indented_code_blocks: true, + autolink: true, + tables: true, + underline: true, + highlight: true) + + markdown.render(text).html_safe + end end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 3e0743e9..0fe7b991 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -17,7 +17,6 @@ # with BigBlueButton; if not, see . class ApplicationMailer < ActionMailer::Base - add_template_helper(ThemingHelper) default from: 'from@example.com' layout 'mailer' end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index d05734cf..a28ef222 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -18,74 +18,83 @@ class UserMailer < ApplicationMailer include ApplicationHelper + include ThemingHelper default from: Rails.configuration.smtp_sender - def verify_email(user, url, image, color) + def verify_email(user, url, settings) + @settings = settings @user = user @url = url - @image = image - @color = color + @image = logo_image + @color = user_color mail(to: @user.email, subject: t('landing.welcome')) end - def password_reset(user, url, image, color) + def password_reset(user, url, settings) + @settings = settings @user = user @url = url - @image = image - @color = color + @image = logo_image + @color = user_color mail to: user.email, subject: t('reset_password.subtitle') end - def user_promoted(user, role, url, image, color) + def user_promoted(user, role, url, settings) + @settings = settings @url = url @admin_url = url + "admins" - @image = image - @color = color + @image = logo_image + @color = user_color @role = translated_role_name(role) mail to: user.email, subject: t('mailer.user.promoted.subtitle', role: translated_role_name(role)) end - def user_demoted(user, role, url, image, color) + def user_demoted(user, role, url, settings) + @settings = settings @url = url @root_url = url - @image = image - @color = color + @image = logo_image + @color = user_color @role = translated_role_name(role) mail to: user.email, subject: t('mailer.user.demoted.subtitle', role: translated_role_name(role)) end - def invite_email(name, email, url, image, color) + def invite_email(name, email, url, settings) + @settings = settings @name = name @email = email @url = url - @image = image - @color = color + @image = logo_image + @color = user_color mail to: email, subject: t('mailer.user.invite.subject') end - def approve_user(user, url, image, color) + def approve_user(user, url, settings) + @settings = settings @user = user @url = url - @image = image - @color = color + @image = logo_image + @color = user_color mail to: user.email, subject: t('mailer.user.approve.subject') end - def approval_user_signup(user, url, image, color, admin_emails) + def approval_user_signup(user, url, admin_emails, settings) + @settings = settings @user = user @url = url - @image = image - @color = color + @image = logo_image + @color = user_color mail to: admin_emails, subject: t('mailer.user.approve.signup.subject') end - def invite_user_signup(user, url, image, color, admin_emails) + def invite_user_signup(user, url, admin_emails, settings) + @settings = settings @user = user @url = url - @image = image - @color = color + @image = logo_image + @color = user_color mail to: admin_emails, subject: t('mailer.user.invite.signup.subject') end diff --git a/app/models/ability.rb b/app/models/ability.rb index eb9732e2..2c9fb9a2 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -27,8 +27,7 @@ class Ability else highest_role = user.highest_priority_role if highest_role.can_edit_site_settings - can [:index, :site_settings, :server_recordings, :branding, :coloring, :coloring_lighten, :coloring_darken, - :room_authentication, :registration_method, :room_limit, :default_recording_visibility], :admin + can [:index, :site_settings, :server_recordings, :update_settings, :coloring, :registration_method], :admin end if highest_role.can_edit_roles diff --git a/app/models/room.rb b/app/models/room.rb index 2de7bc1c..23570167 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -19,128 +19,28 @@ require 'bbb_api' class Room < ApplicationRecord - include ::BbbApi - before_create :setup - before_destroy :delete_all_recordings - validates :name, presence: true belongs_to :owner, class_name: 'User', foreign_key: :user_id - META_LISTED = "gl-listed" - # Determines if a user owns a room. def owned_by?(user) return false if user.nil? user.rooms.include?(self) end - # Checks if a room is running on the BigBlueButton server. - def running? - bbb(owner.provider).is_meeting_running?(bbb_id) - end - # Determines the invite path for the room. def invite_path "#{Rails.configuration.relative_url_root}/#{CGI.escape(uid)}" end - # Creates a meeting on the BigBlueButton server. - def start_session(options = {}) - create_options = { - record: options[:meeting_recorded].to_s, - logoutURL: options[:meeting_logout_url] || '', - moderatorPW: moderator_pw, - attendeePW: attendee_pw, - moderatorOnlyMessage: options[:moderator_message], - muteOnStart: options[:mute_on_start] || false, - "meta_#{META_LISTED}": options[:recording_default_visibility] || false, - "meta_bbb-origin-version": Greenlight::Application::VERSION, - "meta_bbb-origin": "Greenlight", - "meta_bbb-origin-server-name": options[:host] - } - - create_options[:guestPolicy] = "ASK_MODERATOR" if options[:require_moderator_approval] - - # Send the create request. - begin - meeting = bbb(owner.provider).create_meeting(name, bbb_id, create_options) - # Update session info. - unless meeting[:messageKey] == 'duplicateWarning' - update_attributes(sessions: sessions + 1, - last_session: DateTime.now) - end - rescue BigBlueButton::BigBlueButtonException => e - puts "BigBlueButton failed on create: #{e.key}: #{e.message}" - raise e - end - end - - # Returns a URL to join a user into a meeting. - def join_path(name, options = {}, uid = nil) - # Create the meeting, even if it's running - start_session(options) - - # Set meeting options. - options[:meeting_logout_url] ||= nil - options[:moderator_message] ||= '' - options[:user_is_moderator] ||= false - options[:meeting_recorded] ||= false - - return call_invalid_res unless bbb(owner.provider) - - # Get the meeting info. - meeting_info = bbb(owner.provider).get_meeting_info(bbb_id, nil) - - # Determine the password to use when joining. - password = if options[:user_is_moderator] - meeting_info[:moderatorPW] - else - meeting_info[:attendeePW] - end - - # Generate the join URL. - join_opts = {} - join_opts[:userID] = uid if uid - join_opts[:join_via_html5] = true - - join_opts[:guest] = true if options[:require_moderator_approval] && !options[:user_is_moderator] - - bbb(owner.provider).join_meeting_url(bbb_id, name, password, join_opts) - end - # Notify waiting users that a meeting has started. def notify_waiting ActionCable.server.broadcast("#{uid}_waiting_channel", action: "started") end - # Retrieves all the users in a room. - def participants - res = bbb(owner.provider).get_meeting_info(bbb_id, nil) - res[:attendees].map do |att| - User.find_by(uid: att[:userID], name: att[:fullName]) - end - rescue BigBlueButton::BigBlueButtonException - # The meeting is most likely not running. - [] - end - - def recording_count - bbb(owner.provider).get_recordings(meetingID: bbb_id)[:recordings].length - end - - def update_recording(record_id, meta) - meta[:recordID] = record_id - bbb(owner.provider).send_api_request("updateRecordings", meta) - end - - # Deletes a recording from a room. - def delete_recording(record_id) - bbb(owner.provider).delete_recordings(record_id) - end - private # Generates a uid for the room and BigBlueButton. @@ -151,12 +51,6 @@ class Room < ApplicationRecord self.attendee_pw = RandomPassword.generate(length: 12) end - # Deletes all recordings associated with the room. - def delete_all_recordings - record_ids = bbb(owner.provider).get_recordings(meetingID: bbb_id)[:recordings].pluck(:recordID) - delete_recording(record_ids) unless record_ids.empty? - end - # Generates a three character uid chunk. def uid_chunk charset = ("a".."z").to_a - %w(b i l o s) + ("2".."9").to_a - %w(5 8) diff --git a/app/models/user.rb b/app/models/user.rb index 92ed8c74..90c1f9b2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,8 +19,6 @@ require 'bbb_api' class User < ApplicationRecord - include ::BbbApi - attr_accessor :reset_token after_create :assign_default_role after_create :initialize_main_room @@ -203,12 +201,7 @@ class User < ApplicationRecord end def greenlight_account? - return true unless provider # For testing cases when provider is set to null - return true if provider == "greenlight" - return false unless Rails.configuration.loadbalanced_configuration - # Proceed with fetching the provider info - provider_info = retrieve_provider_info(provider, 'api2', 'getUserGreenlightCredentials') - provider_info['provider'] == 'greenlight' + social_uid.nil? end def activation_token diff --git a/app/views/account_activations/verify.html.erb b/app/views/account_activations/show.html.erb similarity index 83% rename from app/views/account_activations/verify.html.erb rename to app/views/account_activations/show.html.erb index 3fc03ff2..1098255f 100644 --- a/app/views/account_activations/verify.html.erb +++ b/app/views/account_activations/show.html.erb @@ -21,7 +21,9 @@

<%= t("verify.not_verified") %>

- <%= render "/shared/components/resend_button" %> +
+ <%= button_to t("verify.resend"), resend_email_path, params: { email: params['email'], email_verified: false }, class: "btn btn-primary btn-space" %> +
diff --git a/app/views/shared/components/_admins_role.html.erb b/app/views/admins/components/_admins_role.html.erb similarity index 100% rename from app/views/shared/components/_admins_role.html.erb rename to app/views/admins/components/_admins_role.html.erb diff --git a/app/views/shared/components/_admins_tags.html.erb b/app/views/admins/components/_admins_tags.html.erb similarity index 100% rename from app/views/shared/components/_admins_tags.html.erb rename to app/views/admins/components/_admins_tags.html.erb diff --git a/app/views/admins/components/_settings.html.erb b/app/views/admins/components/_settings.html.erb index c90d7862..0b2fd482 100644 --- a/app/views/admins/components/_settings.html.erb +++ b/app/views/admins/components/_settings.html.erb @@ -22,7 +22,7 @@
- +
@@ -34,9 +34,9 @@
- - - + + "> + ">
<%= t("administrator.site_settings.color.regular") %> @@ -64,13 +64,13 @@ <%= registration_method_string %> @@ -88,10 +88,10 @@ <%= room_authentication_string %> @@ -109,10 +109,10 @@ <%= recording_default_visibility_string %> @@ -128,25 +128,25 @@
diff --git a/app/views/admins/components/_users.html.erb b/app/views/admins/components/_users.html.erb index 21946232..aa0a6a3c 100644 --- a/app/views/admins/components/_users.html.erb +++ b/app/views/admins/components/_users.html.erb @@ -29,7 +29,7 @@ %> <% unless @role.nil? %> - <%= render "shared/components/admins_tags" %> + <%= render "admins/components/admins_tags" %> <% end %>
@@ -88,7 +88,7 @@ <%= user.provider %> <% roles = user.roles().pluck(:name) %> - <%= render "shared/components/admins_role", role: user.highest_priority_role %> + <%= render "admins/components/admins_role", role: user.highest_priority_role %> <% if roles.include?("pending") %> diff --git a/app/views/admins/edit_user.html.erb b/app/views/admins/edit_user.html.erb index 54beeb8e..2b8f39ed 100644 --- a/app/views/admins/edit_user.html.erb +++ b/app/views/admins/edit_user.html.erb @@ -21,7 +21,7 @@ <%= render "admins/components/menu_buttons" %>
- <%= render "shared/settings/setting_view", setting_id: "account", setting_title: t("settings.account.subtitle") %> + <%= render "users/components/setting_view", setting_id: "account", setting_title: t("settings.account.subtitle") %>
diff --git a/app/views/shared/_features.html.erb b/app/views/main/components/_features.html.erb similarity index 100% rename from app/views/shared/_features.html.erb rename to app/views/main/components/_features.html.erb diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb index 6ecab633..d33db5be 100755 --- a/app/views/main/index.html.erb +++ b/app/views/main/index.html.erb @@ -28,4 +28,4 @@
-<%= render "shared/features" %> +<%= render "main/components/features" %> diff --git a/app/views/shared/components/_create_room_block.html.erb b/app/views/rooms/components/_create_room_block.html.erb similarity index 100% rename from app/views/shared/components/_create_room_block.html.erb rename to app/views/rooms/components/_create_room_block.html.erb diff --git a/app/views/shared/components/_room_block.html.erb b/app/views/rooms/components/_room_block.html.erb similarity index 100% rename from app/views/shared/components/_room_block.html.erb rename to app/views/rooms/components/_room_block.html.erb diff --git a/app/views/shared/_room_event.html.erb b/app/views/rooms/components/_room_event.html.erb similarity index 100% rename from app/views/shared/_room_event.html.erb rename to app/views/rooms/components/_room_event.html.erb diff --git a/app/views/rooms/join.html.erb b/app/views/rooms/join.html.erb index 1e8496a4..84cb6e88 100644 --- a/app/views/rooms/join.html.erb +++ b/app/views/rooms/join.html.erb @@ -14,7 +14,7 @@ %> <% valid_access_code = @room.access_code.nil? || @room.access_code.empty? || @room.access_code == session[:access_code] %> -<%= render 'shared/room_event', render_recordings: valid_access_code do %> +<%= render 'rooms/components/room_event', render_recordings: valid_access_code do %> <% if room_authentication_required %>

<%= t("administrator.site_settings.authentication.user-info") %>

<% elsif !valid_access_code %> @@ -43,7 +43,7 @@ readonly: !current_user.nil?, autofocus: true %> - <%= f.submit (!@is_running && @anyone_can_start)? t("room.start") : t("room.join"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %> + <%= f.submit (!@room_running && @anyone_can_start)? t("room.start") : t("room.join"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %> <% end %> <% end %> diff --git a/app/views/rooms/show.html.erb b/app/views/rooms/show.html.erb index 484b9f87..c8e55845 100644 --- a/app/views/rooms/show.html.erb +++ b/app/views/rooms/show.html.erb @@ -66,7 +66,7 @@ <% end %>
- <% if @is_running %> + <% if @room_running %> <%= button_to t("room.join"), room_path(@room), class: "btn btn-primary btn-block px-7 start-button float-right" %> <% else %> <% unless exceeds_limit %> @@ -80,20 +80,20 @@ <% if current_user.rooms.length > 1 %>
<%= link_to current_user.main_room do %> - <%= render "shared/components/room_block", room: current_user.main_room %> + <%= render "rooms/components/room_block", room: current_user.main_room %> <% end %>
<% current_user.secondary_rooms.each do |room| %>
<%= link_to room do %> - <%= render "shared/components/room_block", room: room %> + <%= render "rooms/components/room_block", room: room %> <% end %>
- <%= render "shared/modals/delete_room_modal", recording_count: room.recording_count, room: room %> + <%= render "shared/modals/delete_room_modal", room: room %> <% end %> <% end %> <% unless room_limit_exceeded %> - <%= render "shared/components/create_room_block"%> + <%= render "rooms/components/create_room_block"%> <% end %>
diff --git a/app/views/rooms/wait.html.erb b/app/views/rooms/wait.html.erb index e93f153c..39171fbf 100644 --- a/app/views/rooms/wait.html.erb +++ b/app/views/rooms/wait.html.erb @@ -13,7 +13,7 @@ # with BigBlueButton; if not, see . %> -<%= render 'shared/room_event', render_recordings: true do %> +<%= render 'rooms/components/room_event', render_recordings: true do %>

<%= t("room.wait.message") %>

diff --git a/app/views/shared/components/_resend_button.html.erb b/app/views/shared/components/_resend_button.html.erb deleted file mode 100644 index 368b347f..00000000 --- a/app/views/shared/components/_resend_button.html.erb +++ /dev/null @@ -1,18 +0,0 @@ -<% -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . -%> - -
- <%= button_to t("verify.resend"), resend_email_path, params: { email: params['email'], email_verified: false }, class: "btn btn-primary btn-space" %> -
diff --git a/app/views/shared/components/_subtitle.html.erb b/app/views/shared/components/_subtitle.html.erb index f051494a..c959035a 100644 --- a/app/views/shared/components/_subtitle.html.erb +++ b/app/views/shared/components/_subtitle.html.erb @@ -14,12 +14,13 @@ %>
-
-

<%= subtitle %>

-
<% if search %> +
+

<%= subtitle %>

+
+
- <% if display_invite %> + <% if invite_registration %>
<%= link_to "#inviteModal", :class => "btn btn-primary", "data-toggle": "modal" do %> <%= t("administrator.users.invite") %> @@ -43,6 +44,10 @@
+ <% else %> +
+

<%= subtitle %>

+
<% end %>
diff --git a/app/views/shared/components/_terms_button.html.erb b/app/views/shared/components/_terms_button.html.erb deleted file mode 100644 index de46d390..00000000 --- a/app/views/shared/components/_terms_button.html.erb +++ /dev/null @@ -1,18 +0,0 @@ -<% -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . -%> - -
- <%= button_to t("terms.accept_existing"), terms_path, params: { accept: true }, class: "btn btn-primary btn-space" %> -
\ No newline at end of file diff --git a/app/views/shared/modals/_delete_room_modal.html.erb b/app/views/shared/modals/_delete_room_modal.html.erb index 3b7a1d8d..1bc42949 100644 --- a/app/views/shared/modals/_delete_room_modal.html.erb +++ b/app/views/shared/modals/_delete_room_modal.html.erb @@ -34,8 +34,8 @@ diff --git a/app/views/shared/components/_confirm_button.html.erb b/app/views/users/change_password.html.erb similarity index 67% rename from app/views/shared/components/_confirm_button.html.erb rename to app/views/users/change_password.html.erb index 8fdba35b..a06f02b7 100644 --- a/app/views/shared/components/_confirm_button.html.erb +++ b/app/views/users/change_password.html.erb @@ -12,7 +12,15 @@ # You should have received a copy of the GNU Lesser General Public License along # with BigBlueButton; if not, see . %> +
+ <%= render "shared/components/subtitle", subtitle: t("settings.title"), search: false %> -
- <%= button_to t("verify.accept"), confirm_path, params: { user_uid: params[:user_uid], email_verified: true }, class: "btn btn-primary btn-space" %> +
+
+ <%= render "users/components/menu_buttons" %> +
+
+ <%= render "users/components/setting_view", setting_id: "password", setting_title: t("settings.password.subtitle") %> +
+
diff --git a/app/views/shared/settings/_account.html.erb b/app/views/users/components/_account.html.erb similarity index 100% rename from app/views/shared/settings/_account.html.erb rename to app/views/users/components/_account.html.erb diff --git a/app/views/shared/settings/_delete.html.erb b/app/views/users/components/_delete.html.erb similarity index 100% rename from app/views/shared/settings/_delete.html.erb rename to app/views/users/components/_delete.html.erb diff --git a/app/views/users/components/_menu_buttons.html.erb b/app/views/users/components/_menu_buttons.html.erb new file mode 100644 index 00000000..860aa86d --- /dev/null +++ b/app/views/users/components/_menu_buttons.html.erb @@ -0,0 +1,26 @@ +<% +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . +%> + +
+ <%= link_to edit_user_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "edit"}" do %> + <%= t("settings.account.title") %> + <% end %> + <%= link_to change_password_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "change_password"}" do %> + <%= t("settings.password.title") %> + <% end %> + <%= link_to delete_account_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "delete_account"}" do %> + <%= t("settings.delete.title") %> + <% end %> +
\ No newline at end of file diff --git a/app/views/shared/settings/_password.html.erb b/app/views/users/components/_password.html.erb similarity index 100% rename from app/views/shared/settings/_password.html.erb rename to app/views/users/components/_password.html.erb diff --git a/app/views/shared/settings/_setting_view.html.erb b/app/views/users/components/_setting_view.html.erb similarity index 92% rename from app/views/shared/settings/_setting_view.html.erb rename to app/views/users/components/_setting_view.html.erb index 4c8b8bd2..915cdb06 100644 --- a/app/views/shared/settings/_setting_view.html.erb +++ b/app/views/users/components/_setting_view.html.erb @@ -17,10 +17,10 @@
- <%= render "shared/components/subtitle", subtitle: setting_title, search: setting_id == "users" %> + <%= render "shared/components/subtitle", subtitle: setting_title, search: false %>
- <%= render "shared/settings/#{setting_id}" %> + <%= render "users/components/#{setting_id}" %>
<% end %> diff --git a/app/views/shared/settings/_design.html.erb b/app/views/users/delete_account.html.erb similarity index 70% rename from app/views/shared/settings/_design.html.erb rename to app/views/users/delete_account.html.erb index e4f794c4..c05727cf 100644 --- a/app/views/shared/settings/_design.html.erb +++ b/app/views/users/delete_account.html.erb @@ -12,11 +12,15 @@ # You should have received a copy of the GNU Lesser General Public License along # with BigBlueButton; if not, see . %> +
+ <%= render "shared/components/subtitle", subtitle: t("settings.title"), search: false %> -
-
-
<%= t("settings.design.not_supported") %>
+
+ <%= render "users/components/menu_buttons" %> +
+
+ <%= render "users/components/setting_view", setting_id: "delete", setting_title: t("settings.delete.subtitle") %>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 8ee6186d..0c7eefdb 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -12,48 +12,15 @@ # You should have received a copy of the GNU Lesser General Public License along # with BigBlueButton; if not, see . %> -
<%= render "shared/components/subtitle", subtitle: t("settings.title"), search: false %>
-
- - - - <% if @user.social_uid.nil? %> - - <% end %> - - -
- - <% if @user.errors.any? %> -
<%= t("errors.title") %>:
-
    - <% @user.errors.full_messages.each do |err| %> -
  • <%= err %>.
  • - <% end %> -
- <% end %> + <%= render "users/components/menu_buttons" %>
- -
- <%= render "shared/settings/setting_view", setting_id: "account", setting_title: t("settings.account.subtitle") %> - - <% if @user.social_uid.nil? %> - <%= render "shared/settings/setting_view", setting_id: "password", setting_title: t("settings.password.subtitle") %> - <% end %> - - <%= render "shared/settings/setting_view", setting_id: "delete", setting_title: t("settings.delete.subtitle") %> + <%= render "users/components/setting_view", setting_id: "account", setting_title: t("settings.account.subtitle") %>
diff --git a/app/views/users/terms.html.erb b/app/views/users/terms.html.erb index 488d3009..62f7a708 100644 --- a/app/views/users/terms.html.erb +++ b/app/views/users/terms.html.erb @@ -24,7 +24,9 @@ <%= markdown(Rails.configuration.terms) %>
<% if Rails.configuration.terms && current_user && !current_user.accepted_terms %> - <%= render "/shared/components/terms_button" %> +
+ <%= button_to t("terms.accept_existing"), terms_path, params: { accept: true }, class: "btn btn-primary btn-space" %> +
<% end %>
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb index d6f059f0..2f4b4f6b 100644 --- a/config/initializers/omniauth.rb +++ b/config/initializers/omniauth.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true require 'office365' +require 'omniauth_options' + +include OmniauthOptions # List of supported Omniauth providers. Rails.application.config.providers = [] @@ -16,7 +19,7 @@ Rails.application.config.omniauth_office365 = ENV['OFFICE365_KEY'].present? && ENV['OFFICE365_SECRET'].present? SETUP_PROC = lambda do |env| - SessionsController.helpers.omniauth_options env + OmniauthOptions.omniauth_options env end OmniAuth.config.logger = Rails.logger diff --git a/config/locales/en.yml b/config/locales/en.yml index 9966b463..0c5c68f2 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -88,10 +88,9 @@ en: roles: can_create_rooms: Can create rooms delete: Delete the role - duplicate_name: The role name you provided was a duplicate. All role names must be unique - empty_name: All roles must have a non empty name - invalid_order: The user role must be the lowest priority role and the admin role must be the highest priority role - invalid_update: You can't update a role with a higher priority than your own role + invalid_create: There was a problem creating a new role. Please check the role values and try again + invalid_order: There was a problem updating the priority of the role. Please check the values and try again + invalid_update: There was a problem updating the permissions of the role. Please check the values and try again name: Role Name new_role: Create a new role role_has_users: This role is assigned to %{user_count} accounts. Please remove all accounts from this role before deleting it. @@ -101,8 +100,7 @@ en: edit_site_settings: Allow users with this role to edit site settings edit_roles: Allow users with this role to edit other roles manage_users: Allow users with this role to manage users - invalid_assignment: You can't assign a role with a higher priority than your own to a user - invalid_removal: You can't remove a role with a higher priority than your own + invalid_assignment: There was a problem assigning the roles to the user. Please check the values and try again colour: title: Role Colour info: Set the colour that will be associated with the role diff --git a/config/routes.rb b/config/routes.rb index 49b80ce3..850c5266 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -37,25 +37,23 @@ Rails.application.routes.draw do resources :admins, only: [:index] scope '/admins' do - get '/site_settings', to: 'admins#site_settings', as: :admin_site_settings + # Panel Tabs get '/recordings', to: 'admins#server_recordings', as: :admin_recordings - post '/branding', to: 'admins#branding', as: :admin_branding - post '/coloring', to: 'admins#coloring', as: :admin_coloring - post '/room_authentication', to: 'admins#room_authentication', as: :admin_room_authentication - post '/coloring_lighten', to: 'admins#coloring_lighten', as: :admin_coloring_lighten - post '/coloring_darken', to: 'admins#coloring_darken', as: :admin_coloring_darken - post '/signup', to: 'admins#signup', as: :admin_signup + get '/site_settings', to: 'admins#site_settings', as: :admin_site_settings + get '/roles', to: 'admins#roles', as: :admin_roles + # Manage Users get '/edit/:user_uid', to: 'admins#edit_user', as: :admin_edit_user post '/ban/:user_uid', to: 'admins#ban_user', as: :admin_ban post '/unban/:user_uid', to: 'admins#unban_user', as: :admin_unban post '/invite', to: 'admins#invite', as: :invite_user - post '/registration_method/:method', to: 'admins#registration_method', as: :admin_change_registration post '/approve/:user_uid', to: 'admins#approve', as: :admin_approve get '/reset', to: 'admins#reset', as: :admin_reset - post '/room_limit', to: 'admins#room_limit', as: :admin_room_limit - post '/default_recording_visibility', to: 'admins#default_recording_visibility', as: :admin_recording_visibility + # Site Settings + post '/update_settings', to: 'admins#update_settings', as: :admin_update_settings + post '/registration_method', to: 'admins#registration_method', as: :admin_change_registration + post '/coloring', to: 'admins#coloring', as: :admin_coloring post '/clear_cache', to: 'admins#clear_cache', as: :admin_clear_cache - get '/roles', to: 'admins#roles', as: :admin_roles + # Roles post '/role', to: 'admins#new_role', as: :admin_new_role patch 'roles/order', to: 'admins#change_role_order', as: :admin_roles_order post '/role/:role_id', to: 'admins#update_role', as: :admin_update_role @@ -86,6 +84,8 @@ Rails.application.routes.draw do # Account management. get '/:user_uid/edit', to: 'users#edit', as: :edit_user + get '/:user_uid/change_password', to: 'users#change_password', as: :change_password + get '/:user_uid/delete_account', to: 'users#delete_account', as: :delete_account patch '/:user_uid/edit', to: 'users#update', as: :update_user delete '/:user_uid', to: 'users#destroy', as: :delete_user @@ -118,8 +118,8 @@ Rails.application.routes.draw do scope '/:meetingID' do # Manage recordings scope '/:record_id' do - post '/', to: 'recordings#update_recording', as: :update_recording - delete '/', to: 'recordings#delete_recording', as: :delete_recording + post '/', to: 'recordings#update', as: :update_recording + delete '/', to: 'recordings#delete', as: :delete_recording end end diff --git a/lib/omniauth_options.rb b/lib/omniauth_options.rb new file mode 100644 index 00000000..0440f527 --- /dev/null +++ b/lib/omniauth_options.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +module OmniauthOptions + module_function + + def omniauth_options(env) + if env['omniauth.strategy'].options[:name] == "bn_launcher" + protocol = Rails.env.production? ? "https" : env["rack.url_scheme"] + + customer_redirect_url = protocol + "://" + env["SERVER_NAME"] + ":" + + env["SERVER_PORT"] + user_domain = parse_user_domain(env["SERVER_NAME"]) + env['omniauth.strategy'].options[:customer] = user_domain + env['omniauth.strategy'].options[:customer_redirect_url] = customer_redirect_url + env['omniauth.strategy'].options[:default_callback_url] = Rails.configuration.gl_callback_url + + # This is only used in the old launcher and should eventually be removed + env['omniauth.strategy'].options[:checksum] = generate_checksum(user_domain, customer_redirect_url, + Rails.configuration.launcher_secret) + elsif env['omniauth.strategy'].options[:name] == "google" + set_hd(env, ENV['GOOGLE_OAUTH2_HD']) + elsif env['omniauth.strategy'].options[:name] == "office365" + set_hd(env, ENV['OFFICE365_HD']) + end + end + + # Limits the domain that can be used with the provider + def set_hd(env, hd) + if hd + hd_opts = hd.split(',') + env['omniauth.strategy'].options[:hd] = if hd_opts.empty? + nil + elsif hd_opts.length == 1 + hd_opts[0] + else + hd_opts + end + end + end + + # Parses the url for the user domain + def parse_user_domain(hostname) + return hostname.split('.').first if Rails.configuration.url_host.empty? + Rails.configuration.url_host.split(',').each do |url_host| + return hostname.chomp(url_host).chomp('.') if hostname.include?(url_host) + end + '' + end + + # Generates a checksum to use alongside the omniauth request + def generate_checksum(user_domain, redirect_url, secret) + string = user_domain + redirect_url + secret + OpenSSL::Digest.digest('sha1', string).unpack1("H*") + end +end diff --git a/spec/concerns/bbb_server_spec.rb b/spec/concerns/bbb_server_spec.rb new file mode 100644 index 00000000..350bcee0 --- /dev/null +++ b/spec/concerns/bbb_server_spec.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +require "rails_helper" +require 'bigbluebutton_api' + +describe BbbServer do + include BbbServer + + let(:bbb_server) { BigBlueButton::BigBlueButtonApi.new("http://bbb.example.com/bigbluebutton/api", "secret", "0.8") } + + before do + @user = create(:user) + @room = @user.main_room + end + + context "#running?" do + it "should return false when not running" do + expect(room_running?(@room.bbb_id)).to be false + end + + it "should return true when running" do + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:is_meeting_running?).and_return(true) + expect(room_running?(@room.bbb_id)).to be true + end + end + + context "#start_session" do + it "should update latest session info" do + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:create_meeting).and_return( + messageKey: "" + ) + + expect do + start_session(@room) + end.to change { @room.sessions }.by(1) + + expect(@room.last_session).not_to be nil + end + end + + context "#join_path" do + it "should return correct join URL for user" do + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return( + attendeePW: @room.attendee_pw + ) + + endpoint = Rails.configuration.bigbluebutton_endpoint + secret = Rails.configuration.bigbluebutton_secret + fullname = "fullName=Example" + join_via_html5 = "&join_via_html5=true" + meeting_id = "&meetingID=#{@room.bbb_id}" + password = "&password=#{@room.attendee_pw}" + + query = fullname + join_via_html5 + meeting_id + password + checksum_string = "join#{query + secret}" + + checksum = OpenSSL::Digest.digest('sha1', checksum_string).unpack1("H*") + expect(join_path(@room, "Example")).to eql("#{endpoint}join?#{query}&checksum=#{checksum}") + end + end + + context "#recordings" do + it "deletes the recording" do + allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:delete_recordings).and_return( + returncode: true, deleted: true + ) + + expect(delete_recording(Faker::IDNumber.valid)) + .to contain_exactly([:returncode, true], [:deleted, true]) + end + end +end diff --git a/spec/concerns/recorder_spec.rb b/spec/concerns/recorder_spec.rb index 7e082e1f..1a740a24 100644 --- a/spec/concerns/recorder_spec.rb +++ b/spec/concerns/recorder_spec.rb @@ -19,13 +19,15 @@ require "rails_helper" require 'bigbluebutton_api' -shared_examples_for "recorder" do - let(:controller) { described_class } # the class that includes the concern +describe Recorder do + include Recorder + include BbbServer + + let(:bbb_server) { BigBlueButton::BigBlueButtonApi.new("http://bbb.example.com/bigbluebutton/api", "secret", "0.8") } before do @user = create(:user) @room = @user.main_room - allow_any_instance_of(Room).to receive(:owner).and_return(@user) end @@ -44,7 +46,7 @@ shared_examples_for "recorder" do ] ) - expect(recordings(@room.bbb_id, @room.owner.provider)).to contain_exactly( + expect(recordings(@room.bbb_id)).to contain_exactly( name: "Example", playbacks: [ @@ -118,7 +120,7 @@ shared_examples_for "recorder" do ] ) - expect(all_recordings(@user.rooms.pluck(:bbb_id), @user.provider, search: "Exam", column: "name", + expect(all_recordings(@user.rooms.pluck(:bbb_id), search: "Exam", column: "name", direction: "desc")).to eq( [ { @@ -219,7 +221,7 @@ shared_examples_for "recorder" do end it "should filter recordings on name" do - expect(recordings(@room.bbb_id, @room.owner.provider, search: "Exam")).to contain_exactly( + expect(recordings(@room.bbb_id, search: "Exam")).to contain_exactly( { meetingID: @room.bbb_id, name: "aExamaaa", @@ -250,7 +252,7 @@ shared_examples_for "recorder" do end it "should filter recordings on participants" do - expect(recordings(@room.bbb_id, @room.owner.provider, search: "5")).to contain_exactly( + expect(recordings(@room.bbb_id, search: "5")).to contain_exactly( meetingID: @room.bbb_id, name: "aExamaaa", participants: "5", @@ -267,7 +269,7 @@ shared_examples_for "recorder" do end it "should filter recordings on format" do - expect(recordings(@room.bbb_id, @room.owner.provider, search: "presentation")).to contain_exactly( + expect(recordings(@room.bbb_id, search: "presentation")).to contain_exactly( { meetingID: @room.bbb_id, name: "test", @@ -298,7 +300,7 @@ shared_examples_for "recorder" do end it "should filter recordings on visibility" do - expect(recordings(@room.bbb_id, @room.owner.provider, search: "public")).to contain_exactly( + expect(recordings(@room.bbb_id, search: "public")).to contain_exactly( { meetingID: @room.bbb_id, name: "test", @@ -329,7 +331,7 @@ shared_examples_for "recorder" do end it "should filter recordings on metadata name by default" do - expect(recordings(@room.bbb_id, @room.owner.provider, search: "metadata")).to contain_exactly( + expect(recordings(@room.bbb_id, search: "metadata")).to contain_exactly( meetingID: @room.bbb_id, name: "Exam", participants: "1", @@ -385,7 +387,7 @@ shared_examples_for "recorder" do end it "should sort recordings on name" do - expect(recordings(@room.bbb_id, @room.owner.provider, column: "name", direction: "asc")).to eq( + expect(recordings(@room.bbb_id, column: "name", direction: "asc")).to eq( [ { meetingID: @room.bbb_id, @@ -421,7 +423,7 @@ shared_examples_for "recorder" do end it "should sort recordings on participants" do - expect(recordings(@room.bbb_id, @room.owner.provider, column: "users", direction: "desc")).to eq( + expect(recordings(@room.bbb_id, column: "users", direction: "desc")).to eq( [ { meetingID: @room.bbb_id, @@ -457,7 +459,7 @@ shared_examples_for "recorder" do end it "should sort recordings on visibility" do - expect(recordings(@room.bbb_id, @room.owner.provider, column: "visibility", direction: "desc")).to eq( + expect(recordings(@room.bbb_id, column: "visibility", direction: "desc")).to eq( [ { meetingID: @room.bbb_id, @@ -493,7 +495,7 @@ shared_examples_for "recorder" do end it "should sort recordings on length" do - expect(recordings(@room.bbb_id, @room.owner.provider, column: "length", direction: "asc")).to eq( + expect(recordings(@room.bbb_id, column: "length", direction: "asc")).to eq( [ { meetingID: @room.bbb_id, @@ -529,7 +531,7 @@ shared_examples_for "recorder" do end it "should sort recordings on format" do - expect(recordings(@room.bbb_id, @room.owner.provider, column: "formats", direction: "desc")).to eq( + expect(recordings(@room.bbb_id, column: "formats", direction: "desc")).to eq( [ { meetingID: @room.bbb_id, diff --git a/spec/controllers/account_activations_controller_spec.rb b/spec/controllers/account_activations_controller_spec.rb index 9c5c5632..7fb4fcbd 100644 --- a/spec/controllers/account_activations_controller_spec.rb +++ b/spec/controllers/account_activations_controller_spec.rb @@ -37,7 +37,7 @@ describe AccountActivationsController, type: :controller do get :show, params: { email: user.email } - expect(response).to render_template(:verify) + expect(response).to render_template(:show) end end diff --git a/spec/controllers/admins_controller_spec.rb b/spec/controllers/admins_controller_spec.rb index 8a9d73f9..8f440df0 100644 --- a/spec/controllers/admins_controller_spec.rb +++ b/spec/controllers/admins_controller_spec.rb @@ -91,7 +91,7 @@ describe AdminsController, type: :controller do context "POST #invite" do before do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) - allow_any_instance_of(ApplicationController).to receive(:allow_greenlight_users?).and_return(true) + allow_any_instance_of(ApplicationController).to receive(:allow_greenlight_accounts?).and_return(true) allow_any_instance_of(User).to receive(:greenlight_account?).and_return(true) end @@ -177,7 +177,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id fake_image_url = "example.com" - post :branding, params: { url: fake_image_url } + post :update_settings, params: { setting: "Branding Image", value: fake_image_url } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Branding Image") @@ -194,7 +194,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id primary_color = Faker::Color.hex_color - post :coloring, params: { color: primary_color } + post :coloring, params: { value: primary_color } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Primary Color") @@ -209,7 +209,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id primary_color = Faker::Color.hex_color - post :coloring_lighten, params: { color: primary_color } + post :update_settings, params: { setting: "Primary Color Lighten", value: primary_color } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Primary Color Lighten") @@ -224,7 +224,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id primary_color = Faker::Color.hex_color - post :coloring_darken, params: { color: primary_color } + post :update_settings, params: { setting: "Primary Color Darken", value: primary_color } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Primary Color Darken") @@ -243,7 +243,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id - post :registration_method, params: { method: "invite" } + post :registration_method, params: { value: "invite" } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Registration Method") @@ -259,7 +259,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id - post :registration_method, params: { method: "invite" } + post :registration_method, params: { value: "invite" } expect(flash[:alert]).to be_present expect(response).to redirect_to(admin_site_settings_path) @@ -273,7 +273,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id - post :room_authentication, params: { value: "true" } + post :update_settings, params: { setting: "Room Authentication", value: "true" } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Room Authentication") @@ -289,7 +289,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id - post :room_limit, params: { limit: 5 } + post :update_settings, params: { setting: "Room Limit", value: 5 } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Room Limit") @@ -305,7 +305,7 @@ describe AdminsController, type: :controller do @request.session[:user_id] = @admin.id - post :default_recording_visibility, params: { visibility: "public" } + post :update_settings, params: { setting: "Default Recording Visibility", value: "public" } feature = Setting.find_by(provider: "provider1").features.find_by(name: "Default Recording Visibility") @@ -353,7 +353,7 @@ describe AdminsController, type: :controller do post :new_role, params: { role: { name: "admin" } } expect(response).to redirect_to admin_roles_path - expect(flash[:alert]).to eq(I18n.t("administrator.roles.duplicate_name")) + expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_create")) end it "should fail with empty role name" do @@ -362,7 +362,7 @@ describe AdminsController, type: :controller do post :new_role, params: { role: { name: " " } } expect(response).to redirect_to admin_roles_path - expect(flash[:alert]).to eq(I18n.t("administrator.roles.empty_name")) + expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_create")) end it "should create new role and increase user role priority" do @@ -412,7 +412,7 @@ describe AdminsController, type: :controller do patch :change_role_order, params: { role: [new_role3.id, new_role2.id] } - expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_update")) + expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_order")) expect(response).to redirect_to admin_roles_path end @@ -432,7 +432,7 @@ describe AdminsController, type: :controller do patch :change_role_order, params: { role: [new_role3.id, new_role2.id] } - expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_update")) + expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_order")) expect(response).to redirect_to admin_roles_path end @@ -489,7 +489,7 @@ describe AdminsController, type: :controller do patch :update_role, params: { role_id: new_role.id, role: { name: "admin" } } - expect(flash[:alert]).to eq(I18n.t("administrator.roles.duplicate_name")) + expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_update")) expect(response).to redirect_to admin_roles_path(selected_role: new_role.id) end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 0085a6e7..ff05ea6d 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -63,6 +63,64 @@ describe ApplicationController do end end + context "getters" do + it "returns whether user signup is allowed" do + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + + expect(controller.allow_user_signup?).to eql(true) + end + + it "returns whether the default bbb endpoint is being used" do + allow(Rails.configuration).to receive(:bigbluebutton_endpoint) + .and_return("http://test-install.blindsidenetworks.com/bigbluebutton/api/") + allow(Rails.configuration).to receive(:bigbluebutton_endpoint_default) + .and_return("http://test-install.blindsidenetworks.com/bigbluebutton/api/") + + expect(controller.bigbluebutton_endpoint_default?).to eql(true) + end + end + + context "allow_greenlight_accounts" do + it "allows if user sign up is turned on" do + allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(false) + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + + expect(controller.allow_greenlight_accounts?).to eql(true) + end + + it "doesn't allow if user sign up is turned off" do + allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(false) + allow(Rails.configuration).to receive(:allow_user_signup).and_return(false) + + expect(controller.allow_greenlight_accounts?).to eql(false) + end + + it "doesn't allow if user_domain is blank" do + allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + + expect(controller.allow_greenlight_accounts?).to eql(false) + end + + it "allows if user provider is set to greenlight" do + allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + allow(controller).to receive(:retrieve_provider_info).and_return("provider" => "greenlight") + controller.instance_variable_set(:@user_domain, "provider1") + + expect(controller.allow_greenlight_accounts?).to eql(true) + end + + it "doesnt allow if user provider is not set to greenlight" do + allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + allow(controller).to receive(:retrieve_provider_info).and_return("provider" => "google") + controller.instance_variable_set(:@user_domain, "provider1") + + expect(controller.allow_greenlight_accounts?).to eql(false) + end + end + context "errors" do it "renders a BigBlueButton error if a BigBlueButtonException occurrs" do routes.draw { get "error" => "anonymous#error" } @@ -74,7 +132,7 @@ describe ApplicationController do it "renders a 404 error if user is not found" do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) allow(Rails.env).to receive(:test?).and_return(false) - allow_any_instance_of(SessionsHelper).to receive(:parse_user_domain).and_return("fake_provider") + allow_any_instance_of(ApplicationController).to receive(:parse_user_domain).and_return("fake_provider") allow_any_instance_of(BbbApi).to receive(:retrieve_provider_info).and_raise("No user with that id exists") routes.draw { get "user_not_found" => "anonymous#user_not_found" } @@ -86,7 +144,7 @@ describe ApplicationController do it "renders a 404 error if user is not given" do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) allow(Rails.env).to receive(:test?).and_return(false) - allow_any_instance_of(SessionsHelper).to receive(:parse_user_domain).and_return("") + allow_any_instance_of(ApplicationController).to receive(:parse_user_domain).and_return("") allow_any_instance_of(BbbApi).to receive(:retrieve_provider_info).and_raise("Provider not included.") routes.draw { get "user_not_found" => "anonymous#user_not_found" } @@ -98,7 +156,7 @@ describe ApplicationController do it "renders a 500 error if any other error related to bbb api" do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) allow(Rails.env).to receive(:test?).and_return(false) - allow_any_instance_of(SessionsHelper).to receive(:parse_user_domain).and_return("") + allow_any_instance_of(ApplicationController).to receive(:parse_user_domain).and_return("") allow_any_instance_of(BbbApi).to receive(:retrieve_provider_info).and_raise("Other error") routes.draw { get "user_not_found" => "anonymous#user_not_found" } diff --git a/spec/controllers/password_resets_controller_spec.rb b/spec/controllers/password_resets_controller_spec.rb index 5fedb819..82ae4475 100644 --- a/spec/controllers/password_resets_controller_spec.rb +++ b/spec/controllers/password_resets_controller_spec.rb @@ -73,7 +73,9 @@ describe PasswordResetsController, type: :controller do end describe "PATCH #update" do - before { allow(Rails.configuration).to receive(:enable_email_verification).and_return(true) } + before do + allow(Rails.configuration).to receive(:enable_email_verification).and_return(true) + end context "valid user" do it "reloads page with notice if password is empty" do @@ -120,7 +122,7 @@ describe PasswordResetsController, type: :controller do allow(controller).to receive(:valid_user).and_return(nil) allow(controller).to receive(:check_expiration).and_return(nil) - allow(controller).to receive(:current_user).and_return(user) + controller.instance_variable_set(:@user, user) params = { id: token, diff --git a/spec/controllers/recordings_controller_spec.rb b/spec/controllers/recordings_controller_spec.rb index c66764e6..f7f23b14 100644 --- a/spec/controllers/recordings_controller_spec.rb +++ b/spec/controllers/recordings_controller_spec.rb @@ -27,10 +27,10 @@ describe RecordingsController, type: :controller do context "POST #update_recording" do it "updates the recordings details" do - allow_any_instance_of(Room).to receive(:update_recording).and_return(updated: true) + allow_any_instance_of(BbbServer).to receive(:update_recording).and_return(updated: true) @request.session[:user_id] = @user.uid - post :update_recording, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } + post :update, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } expect(response).to have_http_status(302) end @@ -38,7 +38,7 @@ describe RecordingsController, type: :controller do it "redirects to root if not the room owner" do @request.session[:user_id] = @secondary_user.uid - post :update_recording, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } + post :update, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } expect(response).to redirect_to(root_path) end @@ -46,10 +46,10 @@ describe RecordingsController, type: :controller do context "DELETE #delete_recording" do it "deletes the recording" do - allow_any_instance_of(Room).to receive(:delete_recording).and_return(true) + allow_any_instance_of(BbbServer).to receive(:delete_recording).and_return(true) @request.session[:user_id] = @user.uid - post :delete_recording, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } + post :delete, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } expect(response).to have_http_status(302) end @@ -57,7 +57,7 @@ describe RecordingsController, type: :controller do it "redirects to root if not the room owner" do @request.session[:user_id] = @secondary_user.uid - post :delete_recording, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } + post :delete, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, state: "public" } expect(response).to redirect_to(root_path) end diff --git a/spec/controllers/rooms_controller_spec.rb b/spec/controllers/rooms_controller_spec.rb index 1424ab66..e3062ed9 100644 --- a/spec/controllers/rooms_controller_spec.rb +++ b/spec/controllers/rooms_controller_spec.rb @@ -28,8 +28,11 @@ def random_valid_room_params end describe RoomsController, type: :controller do - it_behaves_like "recorder" include Recorder + include BbbServer + + let(:bbb_server) { BigBlueButton::BigBlueButtonApi.new("http://bbb.example.com/bigbluebutton/api", "secret", "0.8") } + describe "GET #show" do before do @user = create(:user) @@ -41,8 +44,7 @@ describe RoomsController, type: :controller do get :show, params: { room_uid: @owner.main_room } - expect(assigns(:recordings)).to eql(recordings(@owner.main_room.bbb_id, @owner.provider)) - expect(assigns(:is_running)).to eql(@owner.main_room.running?) + expect(assigns(:recordings)).to eql(recordings(@owner.main_room.bbb_id)) end it "should be able to search recordings if user is owner" do @@ -199,11 +201,6 @@ describe RoomsController, type: :controller do @user = create(:user) @owner = create(:user) @room = @owner.main_room - - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return( - moderatorPW: "modpass", - attendeePW: "attpass", - ) end it "should use account name if user is logged in and meeting running" do @@ -212,7 +209,7 @@ describe RoomsController, type: :controller do @request.session[:user_id] = @user.id post :join, params: { room_uid: @room, join_name: @user.name } - expect(response).to redirect_to(@owner.main_room.join_path(@user.name, {}, @user.uid)) + expect(response).to redirect_to(join_path(@owner.main_room, @user.name, {}, @user.uid)) end it "should use join name if user is not logged in and meeting running" do @@ -220,7 +217,7 @@ describe RoomsController, type: :controller do post :join, params: { room_uid: @room, join_name: "Join Name" } - expect(response).to redirect_to(@owner.main_room.join_path("Join Name", {})) + expect(response).to redirect_to(join_path(@owner.main_room, "Join Name", {})) end it "should render wait if meeting isn't running" do @@ -243,7 +240,7 @@ describe RoomsController, type: :controller do @request.session[:user_id] = @user.id post :join, params: { room_uid: room, join_name: @user.name } - expect(response).to redirect_to(room.join_path(@user.name, { user_is_moderator: false }, @user.uid)) + expect(response).to redirect_to(join_path(room, @user.name, { user_is_moderator: false }, @user.uid)) end it "should join the room as moderator if room has the all_join_moderator setting" do @@ -257,7 +254,7 @@ describe RoomsController, type: :controller do @request.session[:user_id] = @user.id post :join, params: { room_uid: room, join_name: @user.name } - expect(response).to redirect_to(room.join_path(@user.name, { user_is_moderator: true }, @user.uid)) + expect(response).to redirect_to(join_path(room, @user.name, { user_is_moderator: true }, @user.uid)) end it "should render wait if the correct access code is supplied" do @@ -292,7 +289,7 @@ describe RoomsController, type: :controller do @request.session[:user_id] = @owner.id post :join, params: { room_uid: @room, join_name: @owner.name } - expect(response).to redirect_to(@owner.main_room.join_path(@owner.name, { user_is_moderator: true }, @owner.uid)) + expect(response).to redirect_to(join_path(@owner.main_room, @owner.name, { user_is_moderator: true }, @owner.uid)) end it "redirects to root if owner of room is not verified" do @@ -362,7 +359,7 @@ describe RoomsController, type: :controller do @request.session[:user_id] = @user.id post :start, params: { room_uid: @user.main_room } - expect(response).to redirect_to(@user.main_room.join_path(@user.name, { user_is_moderator: true }, @user.uid)) + expect(response).to redirect_to(join_path(@user.main_room, @user.name, { user_is_moderator: true }, @user.uid)) end it "should bring to room if not owner" do diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 97c71ce5..1a603aac 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -373,7 +373,7 @@ describe UsersController, type: :controller do user.reload - expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_removal")) + expect(flash[:alert]).to eq(I18n.t("administrator.roles.invalid_assignment")) expect(response).to render_template(:edit) end @@ -439,7 +439,6 @@ describe UsersController, type: :controller do it "allows admins to delete users" do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) allow_any_instance_of(User).to receive(:greenlight_account?).and_return(true) - allow_any_instance_of(Room).to receive(:delete_all_recordings).and_return('') allow_any_instance_of(ApplicationController).to receive(:set_user_domain).and_return("provider1") controller.instance_variable_set(:@user_domain, "provider1") diff --git a/spec/helpers/admins_helper_spec.rb b/spec/helpers/admins_helper_spec.rb deleted file mode 100644 index e690bd35..00000000 --- a/spec/helpers/admins_helper_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -require "rails_helper" - -describe AdminsHelper do - describe "edit_disabled" do - it "should disable inputs for roles with a higher priority" do - user = create(:user) - admin_role = Role.find_by(name: "admin", provider: "greenlight") - helper.instance_variable_set(:@selected_role, admin_role) - - allow_any_instance_of(SessionsHelper).to receive(:current_user).and_return(user) - - expect(helper.edit_disabled).to eq(true) - end - - it "should enable inputs for roles with a lower priority" do - user = create(:user) - user.roles << Role.find_by(name: "admin", provider: "greenlight") - user_role = Role.find_by(name: "user", provider: "greenlight") - helper.instance_variable_set(:@selected_role, user_role) - - allow_any_instance_of(SessionsHelper).to receive(:current_user).and_return(user) - - expect(helper.edit_disabled).to eq(false) - end - end -end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index d3514529..fe473c6d 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -20,21 +20,6 @@ require "rails_helper" describe ApplicationHelper do describe "#getter functions" do - it "returns whether user signup is allowed" do - allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) - - expect(helper.allow_user_signup?).to eql(true) - end - - it "returns whether the default bbb endpoint is being used" do - allow(Rails.configuration).to receive(:bigbluebutton_endpoint) - .and_return("http://test-install.blindsidenetworks.com/bigbluebutton/api/") - allow(Rails.configuration).to receive(:bigbluebutton_endpoint_default) - .and_return("http://test-install.blindsidenetworks.com/bigbluebutton/api/") - - expect(helper.bigbluebutton_endpoint_default?).to eql(true) - end - it "returns the correct omniauth login url" do allow(Rails.configuration).to receive(:relative_url_root).and_return("/b") provider = Faker::Company.name @@ -43,51 +28,8 @@ describe ApplicationHelper do end end - describe "#allow_greenlight_accounts" do - it "allows if user sign up is turned on" do - allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(false) - allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) - - expect(helper.allow_greenlight_accounts?).to eql(true) - end - - it "doesn't allow if user sign up is turned off" do - allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(false) - allow(Rails.configuration).to receive(:allow_user_signup).and_return(false) - - expect(helper.allow_greenlight_accounts?).to eql(false) - end - - it "doesn't allow if user_domain is blank" do - allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) - allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) - - expect(helper.allow_greenlight_accounts?).to eql(false) - end - - it "allows if user provider is set to greenlight" do - allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) - allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) - allow(helper).to receive(:retrieve_provider_info).and_return("provider" => "greenlight") - - @user_domain = "provider1" - - expect(helper.allow_greenlight_accounts?).to eql(true) - end - - it "doesnt allow if user provider is not set to greenlight" do - allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) - allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) - allow(helper).to receive(:retrieve_provider_info).and_return("provider" => "google") - - @user_domain = "provider1" - - expect(helper.allow_greenlight_accounts?).to eql(false) - end - end - - describe "role_clour" do - it "should use default if the user doens't have a role" do + describe "role_colur" do + it "should use default if the user doesn't have a role" do expect(helper.role_colour(Role.create(name: "test"))).to eq(Rails.configuration.primary_color_default) end diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb deleted file mode 100644 index eabe2661..00000000 --- a/spec/helpers/users_helper_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. -# -# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). -# -# This program is free software; you can redistribute it and/or modify it under the -# terms of the GNU Lesser General Public License as published by the Free Software -# Foundation; either version 3.0 of the License, or (at your option) any later -# version. -# -# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY -# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with BigBlueButton; if not, see . - -require "rails_helper" - -describe UsersHelper do - describe "disabled roles" do - it "should return roles with a less than or equal to priority for non admins" do - user = create(:user) - allow_any_instance_of(SessionsHelper).to receive(:current_user).and_return(user) - - disabled_roles = helper.disabled_roles(user) - - expect(disabled_roles.count).to eq(1) - end - - it "should return roles with a lesser priority for admins" do - admin = create(:user) - admin.add_role :admin - user = create(:user) - - allow_any_instance_of(SessionsHelper).to receive(:current_user).and_return(admin) - - disabled_roles = helper.disabled_roles(user) - - expect(disabled_roles.count).to eq(1) - end - end -end diff --git a/spec/models/room_spec.rb b/spec/models/room_spec.rb index ab02bb5e..af49df8e 100644 --- a/spec/models/room_spec.rb +++ b/spec/models/room_spec.rb @@ -62,52 +62,6 @@ describe Room, type: :model do end end - context "#running?" do - it "should return false when not running" do - expect(@room.running?).to be false - end - - it "should return true when running" do - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:is_meeting_running?).and_return(true) - expect(@room.running?).to be true - end - end - - context "#start_session" do - it "should update latest session info" do - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:create_meeting).and_return( - messageKey: "" - ) - - expect do - @room.start_session - end.to change { @room.sessions }.by(1) - - expect(@room.last_session).not_to be nil - end - end - - context "#join_path" do - it "should return correct join URL for user" do - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return( - attendeePW: "testpass" - ) - - endpoint = Rails.configuration.bigbluebutton_endpoint - secret = Rails.configuration.bigbluebutton_secret - fullname = "fullName=Example" - join_via_html5 = "&join_via_html5=true" - meeting_id = "&meetingID=#{@room.bbb_id}" - password = "&password=testpass" - - query = fullname + join_via_html5 + meeting_id + password - checksum_string = "join#{query + secret}" - - checksum = OpenSSL::Digest.digest('sha1', checksum_string).unpack1("H*") - expect(@room.join_path("Example")).to eql("#{endpoint}join?#{query}&checksum=#{checksum}") - end - end - context "#notify_waiting" do it "should broadcast to waiting channel with started action" do expect do @@ -115,32 +69,4 @@ describe Room, type: :model do end.to have_broadcasted_to("#{@room.uid}_waiting_channel").with(a_hash_including(action: "started")) end end - - context "#participants" do - it "should link participants to accounts" do - user1 = create(:user) - user2 = create(:user) - - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:get_meeting_info).and_return( - attendees: [ - { userID: user1.uid, fullName: user1.name }, - { userID: "non-matching-uid", fullName: "Guest User" }, - { userID: user2.uid, fullName: user2.name }, - ], - ) - - expect(@room.participants).to contain_exactly(user1, nil, user2) - end - end - - context "#recordings" do - it "deletes the recording" do - allow_any_instance_of(BigBlueButton::BigBlueButtonApi).to receive(:delete_recordings).and_return( - returncode: true, deleted: true - ) - - expect(@room.delete_recording(Faker::IDNumber.valid)) - .to contain_exactly([:returncode, true], [:deleted, true]) - end - end end From 01b8dbbd0e344e3df4a3ff4ff87ca467a8377634 Mon Sep 17 00:00:00 2001 From: farhatahmad <35435341+farhatahmad@users.noreply.github.com> Date: Tue, 27 Aug 2019 11:08:58 -0400 Subject: [PATCH 2/9] GRN2-196: Fixed issues that scrutinizer is complaining about (#765) * Refactored code to improve scrutinizer score * Bug fixes --- app/assets/javascripts/rename.js | 8 +- app/assets/javascripts/search.js | 54 +++---- app/controllers/application_controller.rb | 45 +++--- app/controllers/concerns/authenticator.rb | 4 + app/controllers/concerns/joiner.rb | 94 ++++++++++++ app/controllers/concerns/registrar.rb | 29 ++++ app/controllers/concerns/themer.rb | 18 +-- app/controllers/password_resets_controller.rb | 2 +- app/controllers/recordings_controller.rb | 7 + app/controllers/rooms_controller.rb | 139 +++++------------- app/controllers/sessions_controller.rb | 46 ++++++ app/controllers/themes_controller.rb | 3 +- app/controllers/users_controller.rb | 122 ++++----------- app/helpers/admins_helper.rb | 5 +- app/models/concerns/auth_values.rb | 67 +++++++++ app/models/user.rb | 82 ++--------- .../components/_server_recording_row.html.erb | 2 +- app/views/rooms/show.html.erb | 2 +- .../{users => sessions}/ldap_signin.html.erb | 0 app/views/{users => sessions}/new.html.erb | 0 app/views/{users => sessions}/signin.html.erb | 0 .../components/_public_recording_row.html.erb | 2 +- .../shared/components/_recording_row.html.erb | 2 +- .../shared/components/_subtitle.html.erb | 2 +- app/views/users/change_password.html.erb | 9 ++ .../users/components/_menu_buttons.html.erb | 6 +- app/views/users/components/_password.html.erb | 6 +- config/routes.rb | 7 +- .../password_resets_controller_spec.rb | 5 +- .../controllers/recordings_controller_spec.rb | 13 ++ spec/controllers/rooms_controller_spec.rb | 30 +--- spec/controllers/sessions_controller_spec.rb | 44 ++++++ spec/controllers/users_controller_spec.rb | 41 ------ 33 files changed, 462 insertions(+), 434 deletions(-) create mode 100644 app/controllers/concerns/joiner.rb create mode 100644 app/models/concerns/auth_values.rb rename app/views/{users => sessions}/ldap_signin.html.erb (100%) rename app/views/{users => sessions}/new.html.erb (100%) rename app/views/{users => sessions}/signin.html.erb (100%) diff --git a/app/assets/javascripts/rename.js b/app/assets/javascripts/rename.js index a8f32c6a..49ddbce0 100644 --- a/app/assets/javascripts/rename.js +++ b/app/assets/javascripts/rename.js @@ -124,7 +124,7 @@ $(document).on('turbolinks:load', function(){ submit_update_request({ setting: "rename_header", room_name: element.find('#user-text').text(), - }, element.data('path')); + }, element.data('path'), "POST"); } else if(element.is('#recording-title')){ submit_update_request({ @@ -132,16 +132,16 @@ $(document).on('turbolinks:load', function(){ record_id: element.data('recordid'), record_name: element.find('text').text(), room_uid: element.data('room-uid'), - }, element.data('path')); + }, element.data('path'), "PATCH"); } } // Helper for submitting ajax requests - var submit_update_request = function(data, path){ + var submit_update_request = function(data, path, action){ // Send ajax request for update $.ajax({ url: path, - type: "PATCH", + type: action, data: data, }); } diff --git a/app/assets/javascripts/search.js b/app/assets/javascripts/search.js index 6869ebb5..9c8e0c5c 100644 --- a/app/assets/javascripts/search.js +++ b/app/assets/javascripts/search.js @@ -26,8 +26,7 @@ $(document).on('turbolinks:load', function(){ (controller == "admins" && action == "server_recordings")) { // Submit search if the user hits enter $("#search-input").keypress(function(key) { - var keyPressed = key.which - if (keyPressed == 13) { + if (key.which == 13) { searchPage() } }) @@ -35,8 +34,6 @@ $(document).on('turbolinks:load', function(){ // Add listeners for sort $("th[data-order]").click(function(data){ var header_elem = $(data.target) - var controller = $("body").data('controller'); - var action = $("body").data('action'); if(header_elem.data('order') === 'asc'){ // asc header_elem.data('order', 'desc'); @@ -50,15 +47,10 @@ $(document).on('turbolinks:load', function(){ var search = $("#search-input").val(); - if(controller === "rooms" && action === "show"){ - window.location.replace(window.location.pathname + "?page=1&search=" + search + - "&column=" + header_elem.data("header") + "&direction="+ header_elem.data('order') + - "#recordings-table"); - } - else{ - window.location.replace(window.location.pathname + "?page=1&search=" + search + - "&column=" + header_elem.data("header") + "&direction="+ header_elem.data('order')); - } + var url = window.location.pathname + "?page=1&search=" + search + "&column=" + header_elem.data("header") + + "&direction=" + header_elem.data('order') + + window.location.replace(addRecordingTable(url)) }) if(controller === "rooms" && action === "show"){ @@ -75,42 +67,30 @@ $(document).on('turbolinks:load', function(){ function searchPage() { var search = $("#search-input").val(); - var controller = $("body").data('controller'); - var action = $("body").data('action'); - // Check if the user filtered by role var role = new URL(location.href).searchParams.get('role') var url = window.location.pathname + "?page=1&search=" + search - if (role) { - url += "&role=" + role - } + if (role) { url += "&role=" + role } - if(controller === "rooms" && action === "show"){ - window.location.replace(url + "#recordings-table"); - } else{ - window.location.replace(url); - } - + window.location.replace(addRecordingTable(url)); } // Clears the search bar function clearSearch() { - var controller = $("body").data('controller'); - var action = $("body").data('action'); - var role = new URL(location.href).searchParams.get('role') var url = window.location.pathname + "?page=1" - if (role) { - url += "&role=" + role - } - - if(controller === "rooms" && action === "show"){ - window.location.replace(url + "#recordings-table"); - } else{ - window.location.replace(url); - } + if (role) { url += "&role=" + role } + + window.location.replace(addRecordingTable(url)); +} + +function addRecordingTable(url) { + if($("body").data('controller') === "rooms" && $("body").data('action') === "show") { + url += "#recordings-table" + } + return url } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2b46e004..cc8e01ec 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -18,16 +18,9 @@ class ApplicationController < ActionController::Base include BbbServer - include ThemingHelper - before_action :redirect_to_https - before_action :set_user_domain - before_action :set_user_settings - before_action :maintenance_mode? - before_action :migration_error? - before_action :user_locale - before_action :check_admin_password - before_action :check_user_role + before_action :redirect_to_https, :set_user_domain, :set_user_settings, :maintenance_mode?, :migration_error?, + :user_locale, :check_admin_password, :check_user_role # Manually handle BigBlueButton errors rescue_from BigBlueButton::BigBlueButtonException, with: :handle_bigbluebutton_error @@ -77,6 +70,23 @@ class ApplicationController < ActionController::Base @settings = Setting.find_or_create_by(provider: @user_domain) end + # Redirects the user to a Maintenance page if turned on + def maintenance_mode? + if ENV["MAINTENANCE_MODE"] == "true" + render "errors/greenlight_error", status: 503, formats: :html, + locals: { + status_code: 503, + message: I18n.t("errors.maintenance.message"), + help: I18n.t("errors.maintenance.help"), + } + end + if Rails.configuration.maintenance_window.present? + unless cookies[:maintenance_window] == Rails.configuration.maintenance_window + flash.now[:maintenance] = I18n.t("maintenance.window_alert", date: Rails.configuration.maintenance_window) + end + end + end + # Show an information page when migration fails and there is a version error. def migration_error? render :migration_error, status: 500 unless ENV["DB_MIGRATE_FAILED"].blank? @@ -113,23 +123,6 @@ class ApplicationController < ActionController::Base end end - # Redirects the user to a Maintenance page if turned on - def maintenance_mode? - if ENV["MAINTENANCE_MODE"] == "true" - render "errors/greenlight_error", status: 503, formats: :html, - locals: { - status_code: 503, - message: I18n.t("errors.maintenance.message"), - help: I18n.t("errors.maintenance.help"), - } - end - if Rails.configuration.maintenance_window.present? - unless cookies[:maintenance_window] == Rails.configuration.maintenance_window - flash.now[:maintenance] = I18n.t("maintenance.window_alert", date: Rails.configuration.maintenance_window) - end - end - end - # Relative root helper (when deploying to subdirectory). def relative_root Rails.configuration.relative_url_root || "" diff --git a/app/controllers/concerns/authenticator.rb b/app/controllers/concerns/authenticator.rb index e4ba2c04..3a8c1202 100644 --- a/app/controllers/concerns/authenticator.rb +++ b/app/controllers/concerns/authenticator.rb @@ -56,6 +56,10 @@ module Authenticator end end + def ensure_unauthenticated_except_twitter + redirect_to current_user.main_room if current_user && params[:old_twitter_user_id].nil? + end + # Logs current user out of GreenLight. def logout session.delete(:user_id) if current_user diff --git a/app/controllers/concerns/joiner.rb b/app/controllers/concerns/joiner.rb new file mode 100644 index 00000000..e554d631 --- /dev/null +++ b/app/controllers/concerns/joiner.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +module Joiner + extend ActiveSupport::Concern + + # Displays the join room page to the user + def show_user_join + # Get users name + @name = if current_user + current_user.name + elsif cookies.encrypted[:greenlight_name] + cookies.encrypted[:greenlight_name] + else + "" + end + + @search, @order_column, @order_direction, pub_recs = + public_recordings(@room.bbb_id, params.permit(:search, :column, :direction), true) + + @pagy, @public_recordings = pagy_array(pub_recs) + + render :join + end + + # create or update cookie to track the three most recent rooms a user joined + def save_recent_rooms + if current_user + recently_joined_rooms = cookies.encrypted["#{current_user.uid}_recently_joined_rooms"].to_a + cookies.encrypted["#{current_user.uid}_recently_joined_rooms"] = + recently_joined_rooms.prepend(@room.id).uniq[0..2] + end + end + + def join_room(opts) + room_settings = JSON.parse(@room[:room_settings]) + + if room_running?(@room.bbb_id) || @room.owned_by?(current_user) || room_settings["anyoneCanStart"] + + # Determine if the user needs to join as a moderator. + opts[:user_is_moderator] = @room.owned_by?(current_user) || room_settings["joinModerator"] + + opts[:require_moderator_approval] = room_settings["requireModeratorApproval"] + + if current_user + redirect_to join_path(@room, current_user.name, opts, current_user.uid) + else + join_name = params[:join_name] || params[@room.invite_path][:join_name] + redirect_to join_path(@room, join_name, opts) + end + else + search_params = params[@room.invite_path] || params + @search, @order_column, @order_direction, pub_recs = + public_recordings(@room.bbb_id, search_params.permit(:search, :column, :direction), true) + + @pagy, @public_recordings = pagy_array(pub_recs) + + # They need to wait until the meeting begins. + render :wait + end + end + + def incorrect_user_domain + Rails.configuration.loadbalanced_configuration && @room.owner.provider != @user_domain + end + + # Default, unconfigured meeting options. + def default_meeting_options + invite_msg = I18n.t("invite_message") + { + user_is_moderator: false, + meeting_logout_url: request.base_url + logout_room_path(@room), + meeting_recorded: true, + moderator_message: "#{invite_msg}\n\n#{request.base_url + room_path(@room)}", + host: request.host, + recording_default_visibility: @settings.get_value("Default Recording Visibility") == "public" + } + end +end diff --git a/app/controllers/concerns/registrar.rb b/app/controllers/concerns/registrar.rb index 34a77286..98c38a08 100644 --- a/app/controllers/concerns/registrar.rb +++ b/app/controllers/concerns/registrar.rb @@ -43,4 +43,33 @@ module Registrar { present: false, verified: false } end end + + # Checks if the user passes the requirements to be invited + def passes_invite_reqs + # check if user needs to be invited and IS invited + invitation = check_user_invited(@user.email, session[:invite_token], @user_domain) + + @user.email_verified = true if invitation[:verified] + + invitation[:present] + end + + # Add validation errors to model if they exist + def valid_user_or_captcha + valid_user = @user.valid? + valid_captcha = Rails.configuration.recaptcha_enabled ? verify_recaptcha(model: @user) : true + + logger.error("Support: #{@user.email} creation failed: User params are not valid.") unless valid_user + + valid_user && valid_captcha + end + + # Checks if the user trying to sign in with twitter account + def check_if_twitter_account(log_out = false) + unless params[:old_twitter_user_id].nil? && session[:old_twitter_user_id].nil? + logout if log_out + flash.now[:alert] = I18n.t("registration.deprecated.new_signin") + session[:old_twitter_user_id] = params[:old_twitter_user_id] unless params[:old_twitter_user_id].nil? + end + end end diff --git a/app/controllers/concerns/themer.rb b/app/controllers/concerns/themer.rb index 2893ea27..132e3bbf 100644 --- a/app/controllers/concerns/themer.rb +++ b/app/controllers/concerns/themer.rb @@ -22,22 +22,20 @@ module Themer # Lightens a color by 40% def color_lighten(color) # Uses the built in Sass Engine to lighten the color - - dummy_scss = "h1 { color: $lighten; }" - compiled = SassC::Engine.new("$lighten:lighten(#{color}, 40%);" + dummy_scss, syntax: :scss).render - - string_locater = 'color: ' - color_start = compiled.index(string_locater) + string_locater.length - - compiled[color_start..color_start + 6] + generate_sass("lighten", color, "40%") end # Darkens a color by 10% def color_darken(color) # Uses the built in Sass Engine to darken the color + generate_sass("darken", color, "10%") + end - dummy_scss = "h1 { color: $darken; }" - compiled = SassC::Engine.new("$darken:darken(#{color}, 10%);" + dummy_scss, syntax: :scss).render + private + + def generate_sass(action, color, percentage) + dummy_scss = "h1 { color: $#{action}; }" + compiled = SassC::Engine.new("$#{action}:#{action}(#{color}, #{percentage});" + dummy_scss, syntax: :scss).render string_locater = 'color: ' color_start = compiled.index(string_locater) + string_locater.length diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb index 9c77194b..3c22a43e 100644 --- a/app/controllers/password_resets_controller.rb +++ b/app/controllers/password_resets_controller.rb @@ -39,7 +39,7 @@ class PasswordResetsController < ApplicationController redirect_to root_path rescue # User doesn't exist - redirect_to new_password_reset_path, flash: { alert: I18n.t("no_user_email_exists") } + redirect_to root_path, flash: { success: I18n.t("email_sent", email_type: t("reset_password.subtitle")) } end end diff --git a/app/controllers/recordings_controller.rb b/app/controllers/recordings_controller.rb index d9e7f9e8..b002c918 100644 --- a/app/controllers/recordings_controller.rb +++ b/app/controllers/recordings_controller.rb @@ -34,6 +34,13 @@ class RecordingsController < ApplicationController redirect_back fallback_location: root_path if res[:updated] end + # PATCH /:meetingID/:record_id + def rename + update_recording(params[:record_id], "meta_name" => params[:record_name]) + + redirect_back fallback_location: room_path(@room) + end + # DELETE /:meetingID/:record_id def delete delete_recording(params[:record_id]) diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 1aee8f00..9d9b14dd 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -19,12 +19,13 @@ class RoomsController < ApplicationController include Pagy::Backend include Recorder + include Joiner before_action :validate_accepted_terms, unless: -> { !Rails.configuration.terms } before_action :validate_verified_email, except: [:show, :join], unless: -> { !Rails.configuration.enable_email_verification } before_action :find_room, except: [:create, :join_specific_room] - before_action :verify_room_ownership, except: [:create, :show, :join, :logout, :login, :join_specific_room] + before_action :verify_room_ownership, only: [:destroy, :start, :update_settings] before_action :verify_room_owner_verified, only: [:show, :join], unless: -> { !Rails.configuration.enable_email_verification } before_action :verify_user_not_admin, only: [:show] @@ -42,19 +43,17 @@ class RoomsController < ApplicationController @room.owner = current_user @room.room_settings = create_room_settings_string(room_params) - # Save the room - if @room.save - logger.info "Support: #{current_user.email} has created a new room #{@room.uid}." + # Save the room and redirect if it fails + return redirect_to current_user.main_room, flash: { alert: I18n.t("room.create_room_error") } unless @room.save - # Start the room if auto join was turned on - if room_params[:auto_join] == "1" - start - else - redirect_to @room, flash: { success: I18n.t("room.create_room_success") } - end - else - redirect_to current_user.main_room, flash: { alert: I18n.t("room.create_room_error") } - end + logger.info "Support: #{current_user.email} has created a new room #{@room.uid}." + + # Redirect to room is auto join was not turned on + return redirect_to @room, + flash: { success: I18n.t("room.create_room_success") } unless room_params[:auto_join] == "1" + + # Start the room if auto join was turned on + start end # GET /:room_uid @@ -76,6 +75,7 @@ class RoomsController < ApplicationController render :cant_create_rooms end else +<<<<<<< HEAD return redirect_to root_path, flash: { alert: I18n.t("room.invalid_provider") } if incorrect_user_domain # Get users name @@ -102,9 +102,10 @@ class RoomsController < ApplicationController update_room_attributes("name") elsif params[:setting] == "rename_recording" update_recording(params[:record_id], "meta_name" => params[:record_name]) +======= + show_user_join +>>>>>>> GRN2-196: Fixed issues that scrutinizer is complaining about (#765) end - - redirect_back fallback_location: room_path end # POST /:room_uid @@ -123,19 +124,14 @@ class RoomsController < ApplicationController @join_name = params[@room.invite_path][:join_name] elsif !params[:join_name] # Join name not passed. - return + return redirect_to root_path end end # create or update cookie with join name cookies.encrypted[:greenlight_name] = @join_name unless cookies.encrypted[:greenlight_name] == @join_name - if current_user - # create or update cookie to track the three most recent rooms a user joined - recently_joined_rooms = cookies.encrypted["#{current_user.uid}_recently_joined_rooms"].to_a - cookies.encrypted["#{current_user.uid}_recently_joined_rooms"] = - recently_joined_rooms.prepend(@room.id).uniq[0..2] - end + save_recent_rooms logger.info "Support: #{current_user.present? ? current_user.email : @join_name} is joining room #{@room.uid}" join_room(default_meeting_options) @@ -195,20 +191,25 @@ class RoomsController < ApplicationController def update_settings begin raise "Room name can't be blank" if room_params[:name].empty? + raise "Unauthorized Request" if !@room.owned_by?(current_user) || @room == current_user.main_room - @room = Room.find_by!(uid: params[:room_uid]) # Update the rooms settings - update_room_attributes("settings") + if room_params + room_settings_string = create_room_settings_string(room_params) + @room.update_attributes(room_settings: room_settings_string) + end + # Update the rooms name if it has been changed - update_room_attributes("name") if @room.name != room_params[:name] + @room.update_attributes(name: params[:room_name] || room_params[:name]) if @room.name != room_params[:name] # Update the room's access code if it has changed - update_room_attributes("access_code") if @room.access_code != room_params[:access_code] - rescue => e - logger.error "Error in updating room settings: #{e}" - flash[:alert] = I18n.t("room.update_settings_error") - else + @room.update_attributes(access_code: room_params[:access_code]) if @room.access_code != room_params[:access_code] + flash[:success] = I18n.t("room.update_settings_success") + rescue => e + logger.error "Support: Error in updating room settings: #{e}" + flash[:alert] = I18n.t("room.update_settings_error") end + redirect_to room_path end @@ -231,19 +232,6 @@ class RoomsController < ApplicationController private - def update_room_attributes(update_type) - if @room.owned_by?(current_user) && @room != current_user.main_room - if update_type.eql? "name" - @room.update_attributes(name: params[:room_name] || room_params[:name]) - elsif update_type.eql? "settings" - room_settings_string = create_room_settings_string(room_params) - @room.update_attributes(room_settings: room_settings_string) - elsif update_type.eql? "access_code" - @room.update_attributes(access_code: room_params[:access_code]) - end - end - end - def create_room_settings_string(options) room_settings = {} room_settings["muteOnStart"] = options[:mute_on_join] == "1" @@ -269,18 +257,7 @@ class RoomsController < ApplicationController # Ensure the user is logged into the room they are accessing. def verify_room_ownership - bring_to_room unless @room.owned_by?(current_user) - end - - # Redirects a user to their room. - def bring_to_room - if current_user - # Redirect authenticated users to their room. - redirect_to room_path(current_user.main_room) - else - # Redirect unauthenticated users to root. - redirect_to root_path - end + return redirect_to root_path unless @room.owned_by?(current_user) end def validate_accepted_terms @@ -294,12 +271,7 @@ class RoomsController < ApplicationController def verify_room_owner_verified unless @room.owner.activated? flash[:alert] = t("room.unavailable") - - if current_user && !@room.owned_by?(current_user) - redirect_to current_user.main_room - else - redirect_to root_path - end + redirect_to root_path end end @@ -321,49 +293,4 @@ class RoomsController < ApplicationController current_user.rooms.length >= limit end helper_method :room_limit_exceeded - - def join_room(opts) - room_settings = JSON.parse(@room[:room_settings]) - - if room_running?(@room.bbb_id) || @room.owned_by?(current_user) || room_settings["anyoneCanStart"] - - # Determine if the user needs to join as a moderator. - opts[:user_is_moderator] = @room.owned_by?(current_user) || room_settings["joinModerator"] - - opts[:require_moderator_approval] = room_settings["requireModeratorApproval"] - - if current_user - redirect_to join_path(@room, current_user.name, opts, current_user.uid) - else - join_name = params[:join_name] || params[@room.invite_path][:join_name] - redirect_to join_path(@room, join_name, opts) - end - else - search_params = params[@room.invite_path] || params - @search, @order_column, @order_direction, pub_recs = - public_recordings(@room.bbb_id, search_params.permit(:search, :column, :direction), true) - - @pagy, @public_recordings = pagy_array(pub_recs) - - # They need to wait until the meeting begins. - render :wait - end - end - - def incorrect_user_domain - Rails.configuration.loadbalanced_configuration && @room.owner.provider != @user_domain - end - - # Default, unconfigured meeting options. - def default_meeting_options - invite_msg = I18n.t("invite_message") - { - user_is_moderator: false, - meeting_logout_url: request.base_url + logout_room_path(@room), - meeting_recorded: true, - moderator_message: "#{invite_msg}\n\n#{request.base_url + room_path(@room)}", - host: request.host, - recording_default_visibility: @settings.get_value("Default Recording Visibility") == "public" - } - end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 22c7f396..09eec68e 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -23,6 +23,42 @@ class SessionsController < ApplicationController include LdapAuthenticator skip_before_action :verify_authenticity_token, only: [:omniauth, :fail] + before_action :check_user_signup_allowed, only: [:new] + before_action :ensure_unauthenticated_except_twitter, only: [:new, :signin] + + # GET /signin + def signin + check_if_twitter_account + + providers = configured_providers + if one_provider + provider_path = if Rails.configuration.omniauth_ldap + ldap_signin_path + else + "#{Rails.configuration.relative_url_root}/auth/#{providers.first}" + end + + return redirect_to provider_path + end + end + + # GET /ldap_signin + def ldap_signin + end + + # GET /signup + def new + # Check if the user needs to be invited + if invite_registration + redirect_to root_path, flash: { alert: I18n.t("registration.invite.no_invite") } unless params[:invite_token] + + session[:invite_token] = params[:invite_token] + end + + check_if_twitter_account(true) + + @user = User.new + end # POST /users/login def create @@ -101,10 +137,20 @@ class SessionsController < ApplicationController private + # Verify that GreenLight is configured to allow user signup. + def check_user_signup_allowed + redirect_to root_path unless Rails.configuration.allow_user_signup + end + def session_params params.require(:session).permit(:email, :password) end + def one_provider + (!allow_user_signup? || !allow_greenlight_accounts?) && providers.count == 1 && + !Rails.configuration.loadbalanced_configuration + end + def check_user_exists provider = @auth['provider'] == "bn_launcher" ? @auth['info']['customer'] : @auth['provider'] User.exists?(social_uid: @auth['uid'], provider: provider) diff --git a/app/controllers/themes_controller.rb b/app/controllers/themes_controller.rb index bfbfeb56..f5c32eb2 100644 --- a/app/controllers/themes_controller.rb +++ b/app/controllers/themes_controller.rb @@ -17,7 +17,8 @@ # with BigBlueButton; if not, see . class ThemesController < ApplicationController - skip_before_action :maintenance_mode? + skip_before_action :redirect_to_https, :maintenance_mode?, :migration_error?, :user_locale, + :check_admin_password, :check_user_role # GET /primary def index diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a38f85fb..6bffe8ad 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -25,19 +25,17 @@ class UsersController < ApplicationController include Rolify before_action :find_user, only: [:edit, :change_password, :delete_account, :update, :destroy] - before_action :ensure_unauthenticated, only: [:new, :create, :signin] + before_action :ensure_unauthenticated_except_twitter, only: [:create] + before_action :check_user_signup_allowed, only: [:create] before_action :check_admin_of, only: [:edit, :change_password, :delete_account] # POST /u def create - # Verify that GreenLight is configured to allow user signup. - return unless Rails.configuration.allow_user_signup - @user = User.new(user_params) @user.provider = @user_domain # User or recpatcha is not valid - render(:new) && return unless valid_user_or_captcha + render("sessions/new") && return unless valid_user_or_captcha # Redirect to root if user token is either invalid or expired return redirect_to root_path, flash: { alert: I18n.t("registration.invite.fail") } unless passes_invite_reqs @@ -65,50 +63,6 @@ class UsersController < ApplicationController redirect_to root_path end - # GET /signin - def signin - unless params[:old_twitter_user_id].nil? && session[:old_twitter_user_id].nil? - flash[:alert] = I18n.t("registration.deprecated.new_signin") - session[:old_twitter_user_id] = params[:old_twitter_user_id] unless params[:old_twitter_user_id].nil? - end - - providers = configured_providers - if (!allow_user_signup? || !allow_greenlight_accounts?) && providers.count == 1 && - !Rails.configuration.loadbalanced_configuration - provider_path = if Rails.configuration.omniauth_ldap - ldap_signin_path - else - "#{Rails.configuration.relative_url_root}/auth/#{providers.first}" - end - - return redirect_to provider_path - end - end - - # GET /ldap_signin - def ldap_signin - end - - # GET /signup - def new - return redirect_to root_path unless Rails.configuration.allow_user_signup - - # Check if the user needs to be invited - if invite_registration - redirect_to root_path, flash: { alert: I18n.t("registration.invite.no_invite") } unless params[:invite_token] - - session[:invite_token] = params[:invite_token] - end - - unless params[:old_twitter_user_id].nil? && session[:old_twitter_user_id].nil? - logout - flash.now[:alert] = I18n.t("registration.deprecated.new_signin") - session[:old_twitter_user_id] = params[:old_twitter_user_id] unless params[:old_twitter_user_id].nil? - end - - @user = User.new - end - # GET /u/:user_uid/edit def edit redirect_to root_path unless current_user @@ -116,6 +70,7 @@ class UsersController < ApplicationController # GET /u/:user_uid/change_password def change_password + redirect_to edit_user_path unless current_user.greenlight_account? end # GET /u/:user_uid/delete_account @@ -124,11 +79,11 @@ class UsersController < ApplicationController # PATCH /u/:user_uid/edit def update - redirect_path = current_user.admin_of?(@user) ? admins_path : edit_user_path(@user) + profile = params[:setting] == "password" ? change_password_path(@user) : edit_user_path(@user) + redirect_path = current_user.admin_of?(@user) ? admins_path : profile if params[:setting] == "password" # Update the users password. - errors = {} if @user.authenticate(user_params[:password]) # Verify that the new passwords match. @@ -136,21 +91,18 @@ class UsersController < ApplicationController @user.password = user_params[:new_password] else # New passwords don't match. - errors[:password_confirmation] = "doesn't match" + @user.errors.add(:password_confirmation, "doesn't match") end else # Original password is incorrect, can't update. - errors[:password] = "is incorrect" + @user.errors.add(:password, "is incorrect") end - if errors.empty? && @user.save - # Notify the user that their account has been updated. - redirect_to redirect_path, flash: { success: I18n.t("info_update_success") } - else - # Append custom errors. - errors.each { |k, v| @user.errors.add(k, v) } - render :edit, params: { settings: params[:settings] } - end + # Notify the user that their account has been updated. + return redirect_to redirect_path, + flash: { success: I18n.t("info_update_success") } if @user.errors.empty? && @user.save + + render :change_password else if @user.update_attributes(user_params) @user.update_attributes(email_verified: false) if user_params[:email] != @user.email @@ -164,7 +116,7 @@ class UsersController < ApplicationController end end - render :edit, params: { settings: params[:settings] } + render :edit end end @@ -172,20 +124,19 @@ class UsersController < ApplicationController def destroy logger.info "Support: #{current_user.email} is deleting #{@user.email}." - if current_user && current_user == @user - @user.destroy - session.delete(:user_id) - elsif current_user.admin_of?(@user) - begin + self_delete = current_user == @user + begin + if current_user && (self_delete || current_user.admin_of?(@user)) @user.destroy - rescue => e - logger.error "Support: Error in user deletion: #{e}" - flash[:alert] = I18n.t(params[:message], default: I18n.t("administrator.flash.delete_fail")) - else - flash[:success] = I18n.t("administrator.flash.delete") + session.delete(:user_id) if self_delete + + return redirect_to admins_path, flash: { success: I18n.t("administrator.flash.delete") } unless self_delete end - redirect_to(admins_path) && return + rescue => e + logger.error "Support: Error in user deletion: #{e}" + flash[:alert] = I18n.t(params[:message], default: I18n.t("administrator.flash.delete_fail")) end + redirect_to root_path end @@ -216,8 +167,9 @@ class UsersController < ApplicationController @user = User.where(uid: params[:user_uid]).includes(:roles).first end - def ensure_unauthenticated - redirect_to current_user.main_room if current_user && params[:old_twitter_user_id].nil? + # Verify that GreenLight is configured to allow user signup. + def check_user_signup_allowed + redirect_to root_path unless Rails.configuration.allow_user_signup end def user_params @@ -233,26 +185,6 @@ class UsersController < ApplicationController end end - # Add validation errors to model if they exist - def valid_user_or_captcha - valid_user = @user.valid? - valid_captcha = Rails.configuration.recaptcha_enabled ? verify_recaptcha(model: @user) : true - - logger.error("Support: #{@user.email} creation failed: User params are not valid.") unless valid_user - - valid_user && valid_captcha - end - - # Checks if the user passes the requirements to be invited - def passes_invite_reqs - # check if user needs to be invited and IS invited - invitation = check_user_invited(@user.email, session[:invite_token], @user_domain) - - @user.email_verified = true if invitation[:verified] - - invitation[:present] - end - # Checks that the user is allowed to edit this user def check_admin_of redirect_to current_user.main_room if current_user && @user != current_user && !current_user.admin_of?(@user) diff --git a/app/helpers/admins_helper.rb b/app/helpers/admins_helper.rb index 7dd762e6..aff41f2a 100644 --- a/app/helpers/admins_helper.rb +++ b/app/helpers/admins_helper.rb @@ -24,8 +24,9 @@ module AdminsHelper Room.find_by(bbb_id: room_id).owner.email end - def invite_registration - @settings.get_value("Registration Method") == Rails.configuration.registration_methods[:invite] + def admin_invite_registration + controller_name == "admins" && action_name == "index" && + @settings.get_value("Registration Method") == Rails.configuration.registration_methods[:invite] end def room_authentication_string diff --git a/app/models/concerns/auth_values.rb b/app/models/concerns/auth_values.rb new file mode 100644 index 00000000..06681f9d --- /dev/null +++ b/app/models/concerns/auth_values.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +module AuthValues + extend ActiveSupport::Concern + + # Provider attributes. + def auth_name(auth) + case auth['provider'] + when :office365 + auth['info']['display_name'] + else + auth['info']['name'] + end + end + + def auth_username(auth) + case auth['provider'] + when :google + auth['info']['email'].split('@').first + when :bn_launcher + auth['info']['username'] + else + auth['info']['nickname'] + end + end + + def auth_email(auth) + auth['info']['email'] + end + + def auth_image(auth) + case auth['provider'] + when :twitter + auth['info']['image'].gsub("http", "https").gsub("_normal", "") + else + auth['info']['image'] + end + end + + def auth_roles(user, auth) + unless auth['info']['roles'].nil? + roles = auth['info']['roles'].split(',') + + role_provider = auth['provider'] == "bn_launcher" ? auth['info']['customer'] : "greenlight" + roles.each do |role_name| + role = Role.where(provider: role_provider, name: role_name).first + user.roles << role unless role.nil? + end + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 90c1f9b2..d24997d9 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -20,8 +20,7 @@ require 'bbb_api' class User < ApplicationRecord attr_accessor :reset_token - after_create :assign_default_role - after_create :initialize_main_room + after_create :setup_user before_save { email.try(:downcase!) } @@ -49,6 +48,8 @@ class User < ApplicationRecord has_secure_password(validations: false) class << self + include AuthValues + # Generates a user from omniauth. def from_omniauth(auth) # Provider is the customer name if in loadbalanced config mode @@ -63,54 +64,6 @@ class User < ApplicationRecord u.save! end end - - private - - # Provider attributes. - def auth_name(auth) - case auth['provider'] - when :office365 - auth['info']['display_name'] - else - auth['info']['name'] - end - end - - def auth_username(auth) - case auth['provider'] - when :google - auth['info']['email'].split('@').first - when :bn_launcher - auth['info']['username'] - else - auth['info']['nickname'] - end - end - - def auth_email(auth) - auth['info']['email'] - end - - def auth_image(auth) - case auth['provider'] - when :twitter - auth['info']['image'].gsub("http", "https").gsub("_normal", "") - else - auth['info']['image'] - end - end - - def auth_roles(user, auth) - unless auth['info']['roles'].nil? - roles = auth['info']['roles'].split(',') - - role_provider = auth['provider'] == "bn_launcher" ? auth['info']['customer'] : "greenlight" - roles.each do |role_name| - role = Role.where(provider: role_provider, name: role_name).first - user.roles << role unless role.nil? - end - end - end end def self.admins_search(string, role) @@ -149,21 +102,17 @@ class User < ApplicationRecord # Activates an account and initialize a users main room def activate - update_attribute(:email_verified, true) - update_attribute(:activated_at, Time.zone.now) - save + update_attributes(email_verified: true, activated_at: Time.zone.now) end def activated? - return true unless Rails.configuration.enable_email_verification - email_verified + Rails.configuration.enable_email_verification ? email_verified : true end # Sets the password reset attributes. def create_reset_digest self.reset_token = User.new_token - update_attribute(:reset_digest, User.digest(reset_token)) - update_attribute(:reset_sent_at, Time.zone.now) + update_attributes(reset_digest: User.digest(reset_token), reset_sent_at: Time.zone.now) end # Returns true if the given token matches the digest. @@ -288,8 +237,7 @@ class User < ApplicationRecord def create_reset_activation_digest(token) # Create the digest and persist it. - self.activation_digest = User.digest(token) - save + update_attribute(:activation_digest, User.digest(token)) token end @@ -298,19 +246,17 @@ class User < ApplicationRecord rooms.destroy_all end - # Initializes a room for the user and assign a BigBlueButton user id. - def initialize_main_room - self.uid = "gl-#{(0...12).map { rand(65..90).chr }.join.downcase}" - self.main_room = Room.create!(owner: self, name: I18n.t("home_room")) - save - end + def setup_user + # Initializes a room for the user and assign a BigBlueButton user id. + id = "gl-#{(0...12).map { rand(65..90).chr }.join.downcase}" + room = Room.create!(owner: self, name: I18n.t("home_room")) - # Initialize the user to use the default user role - def assign_default_role + update_attributes(uid: id, main_room: room) + + # Initialize the user to use the default user role role_provider = Rails.configuration.loadbalanced_configuration ? provider : "greenlight" Role.create_default_roles(role_provider) if Role.where(provider: role_provider).count.zero? - add_role(:user) if roles.blank? end diff --git a/app/views/admins/components/_server_recording_row.html.erb b/app/views/admins/components/_server_recording_row.html.erb index 1bfd3767..128a4d7f 100644 --- a/app/views/admins/components/_server_recording_row.html.erb +++ b/app/views/admins/components/_server_recording_row.html.erb @@ -15,7 +15,7 @@ -
+
<% if recording[:metadata][:name] %> <%= recording[:metadata][:name] %> diff --git a/app/views/rooms/show.html.erb b/app/views/rooms/show.html.erb index c8e55845..37013256 100644 --- a/app/views/rooms/show.html.erb +++ b/app/views/rooms/show.html.erb @@ -23,7 +23,7 @@
-
+
<% if current_user.main_room == @room %>

<%= t("home_room") %>

diff --git a/app/views/users/ldap_signin.html.erb b/app/views/sessions/ldap_signin.html.erb similarity index 100% rename from app/views/users/ldap_signin.html.erb rename to app/views/sessions/ldap_signin.html.erb diff --git a/app/views/users/new.html.erb b/app/views/sessions/new.html.erb similarity index 100% rename from app/views/users/new.html.erb rename to app/views/sessions/new.html.erb diff --git a/app/views/users/signin.html.erb b/app/views/sessions/signin.html.erb similarity index 100% rename from app/views/users/signin.html.erb rename to app/views/sessions/signin.html.erb diff --git a/app/views/shared/components/_public_recording_row.html.erb b/app/views/shared/components/_public_recording_row.html.erb index 43be87e5..59102efc 100644 --- a/app/views/shared/components/_public_recording_row.html.erb +++ b/app/views/shared/components/_public_recording_row.html.erb @@ -15,7 +15,7 @@ -
+
<% if recording[:metadata][:name] %> <%= recording[:metadata][:name] %> diff --git a/app/views/shared/components/_recording_row.html.erb b/app/views/shared/components/_recording_row.html.erb index deb79088..1c607583 100644 --- a/app/views/shared/components/_recording_row.html.erb +++ b/app/views/shared/components/_recording_row.html.erb @@ -15,7 +15,7 @@ -
+
<% if recording[:metadata][:name] %> <%= recording[:metadata][:name] %> diff --git a/app/views/shared/components/_subtitle.html.erb b/app/views/shared/components/_subtitle.html.erb index c959035a..fc9a33b6 100644 --- a/app/views/shared/components/_subtitle.html.erb +++ b/app/views/shared/components/_subtitle.html.erb @@ -20,7 +20,7 @@
- <% if invite_registration %> + <% if admin_invite_registration %>
<%= link_to "#inviteModal", :class => "btn btn-primary", "data-toggle": "modal" do %> <%= t("administrator.users.invite") %> diff --git a/app/views/users/change_password.html.erb b/app/views/users/change_password.html.erb index a06f02b7..c930be80 100644 --- a/app/views/users/change_password.html.erb +++ b/app/views/users/change_password.html.erb @@ -18,6 +18,15 @@
<%= render "users/components/menu_buttons" %> + + <% if @user.errors.any? %> +
<%= t("errors.title") %>:
+
    + <% @user.errors.full_messages.each do |err| %> +
  • <%= err %>.
  • + <% end %> +
+ <% end %>
<%= render "users/components/setting_view", setting_id: "password", setting_title: t("settings.password.subtitle") %> diff --git a/app/views/users/components/_menu_buttons.html.erb b/app/views/users/components/_menu_buttons.html.erb index 860aa86d..d6c3e266 100644 --- a/app/views/users/components/_menu_buttons.html.erb +++ b/app/views/users/components/_menu_buttons.html.erb @@ -17,8 +17,10 @@ <%= link_to edit_user_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "edit"}" do %> <%= t("settings.account.title") %> <% end %> - <%= link_to change_password_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "change_password"}" do %> - <%= t("settings.password.title") %> + <% if current_user.greenlight_account? %> + <%= link_to change_password_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "change_password"}" do %> + <%= t("settings.password.title") %> + <% end %> <% end %> <%= link_to delete_account_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "delete_account"}" do %> <%= t("settings.delete.title") %> diff --git a/app/views/users/components/_password.html.erb b/app/views/users/components/_password.html.erb index 4d770dad..2e823243 100644 --- a/app/views/users/components/_password.html.erb +++ b/app/views/users/components/_password.html.erb @@ -19,13 +19,13 @@
<%= f.label :password, t("settings.password.old"), class: "form-label" %> - <%= f.password_field :password, class: "form-control #{form_is_invalid?(@user, :password)}" %> + <%= f.password_field :password, class: "form-control #{form_is_invalid?(@user, :password)}", autocomplete: :off, required: true %>
<%= f.label :new_password, t("settings.password.new"), class: "form-label" %> - <%= f.password_field :new_password, class: "form-control #{form_is_invalid?(@user, :password)}" %> + <%= f.password_field :new_password, class: "form-control #{form_is_invalid?(@user, :password)}", autocomplete: :off, required: true %>
<%= f.label :password_confirmation, t("settings.password.confirmation"), class: "form-label" %> - <%= f.password_field :password_confirmation, class: "form-control #{form_is_invalid?(@user, :password_confirmation)}" %> + <%= f.password_field :password_confirmation, class: "form-control #{form_is_invalid?(@user, :password_confirmation)}", autocomplete: :off, required: true %>
diff --git a/config/routes.rb b/config/routes.rb index 850c5266..17ea941b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,10 +25,10 @@ Rails.application.routes.draw do match '/500', to: 'errors#internal_error', via: :all, as: :internal_error # Signin/Signup routes. - get '/signin', to: 'users#signin', as: :signin - get '/signup', to: 'users#new', as: :signup + get '/signin', to: 'sessions#signin', as: :signin + get '/signup', to: 'sessions#new', as: :signup post '/signup', to: 'users#create', as: :create_user - get '/ldap_signin', to: 'users#ldap_signin', as: :ldap_signin + get '/ldap_signin', to: 'sessions#ldap_signin', as: :ldap_signin # Redirect to terms page match '/terms', to: 'users#terms', via: [:get, :post] @@ -119,6 +119,7 @@ Rails.application.routes.draw do # Manage recordings scope '/:record_id' do post '/', to: 'recordings#update', as: :update_recording + patch '/', to: 'recordings#rename', as: :rename_recording delete '/', to: 'recordings#delete', as: :delete_recording end end diff --git a/spec/controllers/password_resets_controller_spec.rb b/spec/controllers/password_resets_controller_spec.rb index 82ae4475..c8b87664 100644 --- a/spec/controllers/password_resets_controller_spec.rb +++ b/spec/controllers/password_resets_controller_spec.rb @@ -50,7 +50,7 @@ describe PasswordResetsController, type: :controller do expect(response).to redirect_to(root_path) end - it "reloads the page if no email exists in the database" do + it "redirects to root with success flash if email does not exists" do params = { password_reset: { email: nil, @@ -58,7 +58,8 @@ describe PasswordResetsController, type: :controller do } post :create, params: params - expect(response).to redirect_to(new_password_reset_path) + expect(flash[:success]).to be_present + expect(response).to redirect_to(root_path) end end diff --git a/spec/controllers/recordings_controller_spec.rb b/spec/controllers/recordings_controller_spec.rb index f7f23b14..fd5c4988 100644 --- a/spec/controllers/recordings_controller_spec.rb +++ b/spec/controllers/recordings_controller_spec.rb @@ -44,6 +44,19 @@ describe RecordingsController, type: :controller do end end + context "PATCH #rename" do + it "properly updates recording name and redirects to current page" do + allow_any_instance_of(BbbServer).to receive(:update_recording).and_return(updated: true) + + @request.session[:user_id] = @user.id + name = Faker::Games::Pokemon.name + + patch :rename, params: { meetingID: @room.bbb_id, record_id: Faker::IDNumber.valid, record_name: name } + + expect(response).to redirect_to(@room) + end + end + context "DELETE #delete_recording" do it "deletes the recording" do allow_any_instance_of(BbbServer).to receive(:delete_recording).and_return(true) diff --git a/spec/controllers/rooms_controller_spec.rb b/spec/controllers/rooms_controller_spec.rb index e3062ed9..13856960 100644 --- a/spec/controllers/rooms_controller_spec.rb +++ b/spec/controllers/rooms_controller_spec.rb @@ -366,7 +366,7 @@ describe RoomsController, type: :controller do @request.session[:user_id] = @user.id post :start, params: { room_uid: @other_room } - expect(response).to redirect_to(@user.main_room) + expect(response).to redirect_to(root_path) end it "should bring to root if not authenticated" do @@ -405,37 +405,11 @@ describe RoomsController, type: :controller do .from(@secondary_room.room_settings).to(formatted_room_params) expect(response).to redirect_to(@secondary_room) end - end - - describe "PATCH #update" do - before do - @user = create(:user) - @secondary_room = create(:room, owner: @user) - @editable_room = create(:room, owner: @user) - end - - it "properly updates room name through room block and redirects to current page" do - @request.session[:user_id] = @user.id - - patch :update, params: { room_uid: @secondary_room, room_block_uid: @editable_room, - setting: :rename_block, room_name: :name } - - expect(response).to redirect_to(@secondary_room) - end it "properly updates room name through room header and redirects to current page" do @request.session[:user_id] = @user.id - patch :update, params: { room_uid: @secondary_room, setting: :rename_header, room_name: :name } - - expect(response).to redirect_to(@secondary_room) - end - - it "properly updates recording name and redirects to current page" do - @request.session[:user_id] = @user.id - - patch :update, params: { room_uid: @secondary_room, recordid: :recordid, - setting: :rename_recording, record_name: :name } + patch :update_settings, params: { room_uid: @secondary_room, setting: :rename_header, room_name: :name } expect(response).to redirect_to(@secondary_room) end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index d8f2bbc3..d5e5c500 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -19,6 +19,50 @@ require "rails_helper" describe SessionsController, type: :controller do + describe "GET #new" do + it "assigns a blank user to the view" do + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + + get :new + expect(assigns(:user)).to be_a_new(User) + end + + it "redirects to root if allow_user_signup is false" do + allow(Rails.configuration).to receive(:allow_user_signup).and_return(false) + + get :new + expect(response).to redirect_to(root_path) + end + + it "rejects the user if they are not invited" do + allow_any_instance_of(Registrar).to receive(:invite_registration).and_return(true) + allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) + + get :new + + expect(flash[:alert]).to be_present + expect(response).to redirect_to(root_path) + end + end + + describe "GET #signin" do + it "redirects to main room if already authenticated" do + user = create(:user) + @request.session[:user_id] = user.id + + post :signin + expect(response).to redirect_to(room_path(user.main_room)) + end + end + + describe 'GET #ldap_signin' do + it "should render the ldap signin page" do + get :ldap_signin + + expect(response).to render_template(:ldap_signin) + end + end + describe "GET #destroy" do before(:each) do user = create(:user, provider: "greenlight") diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 1a603aac..47db5ee6 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -46,32 +46,6 @@ describe UsersController, type: :controller do } end - describe "GET #new" do - it "assigns a blank user to the view" do - allow(Rails.configuration).to receive(:allow_user_signup).and_return(true) - - get :new - expect(assigns(:user)).to be_a_new(User) - end - - it "redirects to root if allow_user_signup is false" do - allow(Rails.configuration).to receive(:allow_user_signup).and_return(false) - - get :new - expect(response).to redirect_to(root_path) - end - end - - describe "GET #signin" do - it "redirects to main room if already authenticated" do - user = create(:user) - @request.session[:user_id] = user.id - - post :signin - expect(response).to redirect_to(room_path(user.main_room)) - end - end - describe "GET #edit" do it "renders the edit template" do user = create(:user) @@ -211,13 +185,6 @@ describe UsersController, type: :controller do expect { post :create, params: params }.to change { ActionMailer::Base.deliveries.count }.by(1) end - it "rejects the user if they are not invited" do - get :new - - expect(flash[:alert]).to be_present - expect(response).to redirect_to(root_path) - end - it "allows the user to signup if they are invited" do allow(Rails.configuration).to receive(:enable_email_verification).and_return(false) @@ -493,12 +460,4 @@ describe UsersController, type: :controller do expect(response).to redirect_to(root_path) end end - - context 'GET #ldap_signin' do - it "should render the ldap signin page" do - get :ldap_signin - - expect(response).to render_template(:ldap_signin) - end - end end From 666231db6c5a30a54d0087ce0447047f1e7a3023 Mon Sep 17 00:00:00 2001 From: shawn-higgins1 <23224097+shawn-higgins1@users.noreply.github.com> Date: Tue, 27 Aug 2019 11:30:25 -0400 Subject: [PATCH 3/9] Change permissions from columns to table entries (#762) --- app/controllers/concerns/emailer.rb | 2 +- app/controllers/concerns/rolify.rb | 19 +++++-- app/controllers/recordings_controller.rb | 2 +- app/controllers/rooms_controller.rb | 2 +- app/models/ability.rb | 9 ++-- app/models/role.rb | 51 ++++++++++++++++--- app/models/role_permission.rb | 5 ++ app/models/user.rb | 8 +-- .../admins/components/_menu_buttons.html.erb | 6 +-- app/views/admins/components/_roles.html.erb | 26 +++++----- app/views/shared/_header.html.erb | 8 +-- app/views/users/components/_account.html.erb | 6 +-- .../20190822134205_create_role_permissions.rb | 31 +++++++++++ db/schema.rb | 18 ++++--- spec/controllers/admins_controller_spec.rb | 24 +++++---- spec/controllers/rooms_controller_spec.rb | 2 +- spec/controllers/users_controller_spec.rb | 10 ++-- 17 files changed, 163 insertions(+), 66 deletions(-) create mode 100644 app/models/role_permission.rb create mode 100644 db/migrate/20190822134205_create_role_permissions.rb diff --git a/app/controllers/concerns/emailer.rb b/app/controllers/concerns/emailer.rb index 378ad62e..39ee1ea3 100644 --- a/app/controllers/concerns/emailer.rb +++ b/app/controllers/concerns/emailer.rb @@ -128,7 +128,7 @@ module Emailer end def admin_emails - admins = User.all_users_with_roles.where(roles: { can_manage_users: true }) + admins = User.all_users_with_roles.where(roles: { role_permissions: { name: "can_manage_users", value: "true" } }) if Rails.configuration.loadbalanced_configuration admins = admins.without_role(:super_admin) diff --git a/app/controllers/concerns/rolify.rb b/app/controllers/concerns/rolify.rb index 589a6d49..1fab4bc5 100644 --- a/app/controllers/concerns/rolify.rb +++ b/app/controllers/concerns/rolify.rb @@ -48,7 +48,7 @@ module Rolify # Updates a user's roles def update_roles(roles) # Check that the user can manage users - return true unless current_user.highest_priority_role.can_manage_users + return true unless current_user.highest_priority_role.get_permission("can_manage_users") new_roles = roles.split(' ').map(&:to_i) old_roles = @user.roles.pluck(:id) @@ -89,8 +89,8 @@ module Rolify end # Send promoted/demoted emails - added_roles.each { |role| send_user_promoted_email(@user, role) if role.send_promoted_email } - removed_roles.each { |role| send_user_demoted_email(@user, role) if role.send_demoted_email } + added_roles.each { |role| send_user_promoted_email(@user, role) if role.get_permission("send_promoted_email") } + removed_roles.each { |role| send_user_demoted_email(@user, role) if role.get_permission("send_demoted_email") } # Update the roles @user.roles.delete(removed_roles) @@ -143,6 +143,16 @@ module Rolify permission_params = params.require(:role).permit(:can_create_rooms, :send_promoted_email, :send_demoted_email, :can_edit_site_settings, :can_edit_roles, :can_manage_users, :colour) + permission_params.transform_values! do |v| + if v == "0" + "false" + elsif v == "1" + "true" + else + v + end + end + # Role is a default role so users can't change the name role_params[:name] = role.name if Role::RESERVED_ROLE_NAMES.include?(role.name) @@ -154,7 +164,8 @@ module Rolify return false end - role.update(permission_params) + role.update(colour: permission_params[:colour]) + role.update_all_role_permissions(permission_params) role.save! end diff --git a/app/controllers/recordings_controller.rb b/app/controllers/recordings_controller.rb index b002c918..d5d3c80f 100644 --- a/app/controllers/recordings_controller.rb +++ b/app/controllers/recordings_controller.rb @@ -58,7 +58,7 @@ class RecordingsController < ApplicationController # Ensure the user is logged into the room they are accessing. def verify_room_ownership if !current_user || (!@room.owned_by?(current_user) && - !current_user.highest_priority_role.can_edit_site_settings && + !current_user.highest_priority_role.get_permission("can_edit_site_settings") && !current_user.has_role?(:super_admin)) redirect_to root_path end diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 9d9b14dd..e9e1b0c6 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -63,7 +63,7 @@ class RoomsController < ApplicationController # If its the current user's room if current_user && @room.owned_by?(current_user) - if current_user.highest_priority_role.can_create_rooms + if current_user.highest_priority_role.get_permission("can_create_rooms") # User is allowed to have rooms @search, @order_column, @order_direction, recs = recordings(@room.bbb_id, params.permit(:search, :column, :direction), true) diff --git a/app/models/ability.rb b/app/models/ability.rb index 2c9fb9a2..8be21b91 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -26,20 +26,21 @@ class Ability can :manage, :all else highest_role = user.highest_priority_role - if highest_role.can_edit_site_settings + if highest_role.get_permission("can_edit_site_settings") can [:index, :site_settings, :server_recordings, :update_settings, :coloring, :registration_method], :admin end - if highest_role.can_edit_roles + if highest_role.get_permission("can_edit_roles") can [:index, :roles, :new_role, :change_role_order, :update_role, :delete_role], :admin end - if highest_role.can_manage_users + if highest_role.get_permission("can_manage_users") can [:index, :roles, :edit_user, :promote, :demote, :ban_user, :unban_user, :approve, :invite, :reset], :admin end - if !highest_role.can_edit_site_settings && !highest_role.can_edit_roles && !highest_role.can_manage_users + if !highest_role.get_permission("can_edit_site_settings") && !highest_role.get_permission("can_edit_roles") && + !highest_role.get_permission("can_manage_users") cannot :manage, AdminsController end end diff --git a/app/models/role.rb b/app/models/role.rb index 6f0e932d..a4b1331f 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -18,6 +18,7 @@ class Role < ApplicationRecord has_and_belongs_to_many :users, join_table: :users_roles + has_many :role_permissions default_scope { order(:priority) } scope :by_priority, -> { order(:priority) } @@ -30,15 +31,18 @@ class Role < ApplicationRecord end def self.create_default_roles(provider) - Role.create(name: "user", provider: provider, priority: 1, can_create_rooms: true, colour: "#868e96") - Role.create(name: "admin", provider: provider, priority: 0, can_create_rooms: true, send_promoted_email: true, + Role.create(name: "user", provider: provider, priority: 1, colour: "#868e96") + .update_all_role_permissions(can_create_rooms: true) + Role.create(name: "admin", provider: provider, priority: 0, colour: "#f1c40f") + .update_all_role_permissions(can_create_rooms: true, send_promoted_email: true, send_demoted_email: true, can_edit_site_settings: true, - can_edit_roles: true, can_manage_users: true, colour: "#f1c40f") - Role.create(name: "pending", provider: provider, priority: -1, colour: "#17a2b8") - Role.create(name: "denied", provider: provider, priority: -1, colour: "#343a40") - Role.create(name: "super_admin", provider: provider, priority: -2, can_create_rooms: true, + can_edit_roles: true, can_manage_users: true) + Role.create(name: "pending", provider: provider, priority: -1, colour: "#17a2b8").update_all_role_permissions + Role.create(name: "denied", provider: provider, priority: -1, colour: "#343a40").update_all_role_permissions + Role.create(name: "super_admin", provider: provider, priority: -2, colour: "#cd201f") + .update_all_role_permissions(can_create_rooms: true, send_promoted_email: true, send_demoted_email: true, can_edit_site_settings: true, - can_edit_roles: true, can_manage_users: true, colour: "#cd201f") + can_edit_roles: true, can_manage_users: true) end def self.create_new_role(role_name, provider) @@ -56,4 +60,37 @@ class Role < ApplicationRecord role end + + def update_all_role_permissions(permissions = {}) + update_permission("can_create_rooms", permissions[:can_create_rooms].to_s) + update_permission("send_promoted_email", permissions[:send_promoted_email].to_s) + update_permission("send_demoted_email", permissions[:send_demoted_email].to_s) + update_permission("can_edit_site_settings", permissions[:can_edit_site_settings].to_s) + update_permission("can_edit_roles", permissions[:can_edit_roles].to_s) + update_permission("can_manage_users", permissions[:can_manage_users].to_s) + end + + # Updates the value of the permission and enables it + def update_permission(name, value) + permission = role_permissions.find_or_create_by!(name: name) + + permission.update_attributes(value: value, enabled: true) + end + + # Returns the value if enabled or the default if not enabled + def get_permission(name, return_boolean = true) + permission = role_permissions.find_or_create_by!(name: name) + + value = if permission[:enabled] + permission[:value] + else + "false" + end + + if return_boolean + value == "true" + else + value + end + end end diff --git a/app/models/role_permission.rb b/app/models/role_permission.rb new file mode 100644 index 00000000..058b900c --- /dev/null +++ b/app/models/role_permission.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class RolePermission < ApplicationRecord + belongs_to :role +end diff --git a/app/models/user.rb b/app/models/user.rb index d24997d9..52e39bbe 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,7 +29,7 @@ class User < ApplicationRecord has_many :rooms belongs_to :main_room, class_name: 'Room', foreign_key: :room_id, required: false - has_and_belongs_to_many :roles, join_table: :users_roles + has_and_belongs_to_many :roles, -> { includes :role_permissions }, join_table: :users_roles validates :name, length: { maximum: 256 }, presence: true validates :provider, presence: true @@ -163,11 +163,11 @@ class User < ApplicationRecord if has_role? :super_admin id != user.id else - highest_priority_role.can_manage_users && (id != user.id) && (provider == user.provider) && + highest_priority_role.get_permission("can_manage_users") && (id != user.id) && (provider == user.provider) && (!user.has_role? :super_admin) end else - (highest_priority_role.can_manage_users || (has_role? :super_admin)) && (id != user.id) + (highest_priority_role.get_permission("can_manage_users") || (has_role? :super_admin)) && (id != user.id) end end @@ -230,7 +230,7 @@ class User < ApplicationRecord def self.all_users_with_roles User.joins("INNER JOIN users_roles ON users_roles.user_id = users.id INNER JOIN roles " \ - "ON roles.id = users_roles.role_id") + "ON roles.id = users_roles.role_id INNER JOIN role_permissions ON roles.id = role_permissions.role_id").distinct end private diff --git a/app/views/admins/components/_menu_buttons.html.erb b/app/views/admins/components/_menu_buttons.html.erb index 395cc3d4..17bbc460 100644 --- a/app/views/admins/components/_menu_buttons.html.erb +++ b/app/views/admins/components/_menu_buttons.html.erb @@ -16,12 +16,12 @@
<% highest_role = current_user.highest_priority_role %> <% highest_role.name %> - <% if highest_role.can_manage_users || highest_role.name == "super_admin" %> + <% if highest_role.get_permission("can_manage_users") || highest_role.name == "super_admin" %> <%= link_to admins_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "index"}" do %> <%= t("administrator.users.title") %> <% end %> <% end %> - <% if highest_role.can_edit_site_settings || highest_role.name == "super_admin" %> + <% if highest_role.get_permission("can_edit_site_settings") || highest_role.name == "super_admin" %> <%= link_to admin_recordings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_recordings"}" do %> <%= t("administrator.recordings.title") %> <% end %> @@ -29,7 +29,7 @@ <%= t("administrator.site_settings.title") %> <% end %> <% end %> - <% if highest_role.can_edit_roles || highest_role.name == "super_admin" %> + <% if highest_role.get_permission("can_edit_roles") || highest_role.name == "super_admin" %> <%= link_to admin_roles_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "roles"}" do %> <%= t("administrator.roles.title") %> <% end %> diff --git a/app/views/admins/components/_roles.html.erb b/app/views/admins/components/_roles.html.erb index 9d8cf77b..51f5cf14 100644 --- a/app/views/admins/components/_roles.html.erb +++ b/app/views/admins/components/_roles.html.erb @@ -33,7 +33,7 @@
"> - <%= form_for(@selected_role, url: admin_update_role_path(@selected_role.id), method: :post) do |f| %> + <%= form_with model: @selected_role, url: admin_update_role_path(@selected_role.id), method: :post do |f| %> <%= f.label t('administrator.roles.name'), class: "form-label" %> <%= f.text_field :name, class: 'form-control mb-3', value: translated_role_name(@selected_role), readonly: edit_disabled || @selected_role.name == "user" || @selected_role.name == "admin", required: true %> @@ -48,34 +48,34 @@
-
- <% if current_user_role.can_manage_users || current_user_role.name == "super_admin" %> + <% if current_user_role.get_permission("can_manage_users") || current_user_role.name == "super_admin" %> <% provider = Rails.configuration.loadbalanced_configuration ? current_user.provider : "greenlight" %> <%= f.select :roles, Role.editable_roles(@user_domain).map{|role| [translated_role_name(role), role.id, {'data-colour' => role_colour(role)}]}.unshift(["", nil, {'data-colour' => nil}]), {disabled: disabled_roles(@user)}, { class: "form-control custom-select", id: "role-select-dropdown" } %> <% end %> - <%= f.hidden_field :role_ids, id: "user_role_ids", value: @user.roles.by_priority.pluck(:id) %> + <%= f.hidden_field :role_ids, id: "user_role_ids", value: @user.roles.by_priority.pluck(:id).uniq %> <%= f.label t("settings.account.image"), class: "form-label mt-5" %>
diff --git a/db/migrate/20190822134205_create_role_permissions.rb b/db/migrate/20190822134205_create_role_permissions.rb new file mode 100644 index 00000000..ff29feb6 --- /dev/null +++ b/db/migrate/20190822134205_create_role_permissions.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class CreateRolePermissions < ActiveRecord::Migration[5.2] + def change + create_table :role_permissions do |t| + t.string :name + t.string :value, default: "" + t.boolean :enabled, default: false + t.references :role, foreign_key: true + + t.timestamps + end + + Role.all.each do |role| + role.role_permissions.create(name: "can_create_rooms", value: role.can_create_rooms.to_s, enabled: true) + role.role_permissions.create(name: "send_promoted_email", value: role.send_promoted_email.to_s, enabled: true) + role.role_permissions.create(name: "send_demoted_email", value: role.send_demoted_email.to_s, enabled: true) + role.role_permissions.create(name: "can_edit_site_settings", value: role.can_edit_site_settings.to_s, + enabled: true) + role.role_permissions.create(name: "can_edit_roles", value: role.can_edit_roles.to_s, enabled: true) + role.role_permissions.create(name: "can_manage_users", value: role.can_manage_users.to_s, enabled: true) + end + + remove_column :roles, :can_create_rooms + remove_column :roles, :send_promoted_email + remove_column :roles, :send_demoted_email + remove_column :roles, :can_edit_site_settings + remove_column :roles, :can_edit_roles + remove_column :roles, :can_manage_users + end +end diff --git a/db/schema.rb b/db/schema.rb index 874ebad8..27dd362c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_07_26_153012) do +ActiveRecord::Schema.define(version: 2019_08_22_134205) do create_table "features", force: :cascade do |t| t.integer "setting_id" @@ -33,15 +33,19 @@ ActiveRecord::Schema.define(version: 2019_07_26_153012) do t.index ["provider"], name: "index_invitations_on_provider" end + create_table "role_permissions", force: :cascade do |t| + t.string "name" + t.string "value", default: "" + t.boolean "enabled", default: false + t.integer "role_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["role_id"], name: "index_role_permissions_on_role_id" + end + create_table "roles", force: :cascade do |t| t.string "name" t.integer "priority", default: 9999 - t.boolean "can_create_rooms", default: false - t.boolean "send_promoted_email", default: false - t.boolean "send_demoted_email", default: false - t.boolean "can_edit_site_settings", default: false - t.boolean "can_edit_roles", default: false - t.boolean "can_manage_users", default: false t.string "colour" t.string "provider" t.datetime "created_at", null: false diff --git a/spec/controllers/admins_controller_spec.rb b/spec/controllers/admins_controller_spec.rb index 8f440df0..2b9a32ef 100644 --- a/spec/controllers/admins_controller_spec.rb +++ b/spec/controllers/admins_controller_spec.rb @@ -398,7 +398,8 @@ describe AdminsController, type: :controller do it "should fail if a user attempts to edit a role with a higher priority than their own" do Role.create(name: "test1", priority: 1, provider: "greenlight") - new_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight", can_edit_roles: true) + new_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight") + new_role2.update_permission("can_edit_roles", "true") new_role3 = Role.create(name: "test3", priority: 3, provider: "greenlight") user_role = Role.find_by(name: "user", provider: "greenlight") @@ -418,7 +419,8 @@ describe AdminsController, type: :controller do it "should fail if a user attempts to edit a role with a higher priority than their own" do Role.create(name: "test1", priority: 1, provider: "greenlight") - new_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight", can_edit_roles: true) + new_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight") + new_role2.update_permission("can_edit_roles", "true") new_role3 = Role.create(name: "test3", priority: 3, provider: "greenlight") user_role = Role.find_by(name: "user", provider: "greenlight") @@ -465,7 +467,8 @@ describe AdminsController, type: :controller do it "should fail to update a role with a lower priority than the user" do new_role1 = Role.create(name: "test1", priority: 1, provider: "provider1") - new_role2 = Role.create(name: "test2", priority: 2, provider: "provider1", can_edit_roles: true) + new_role2 = Role.create(name: "test2", priority: 2, provider: "provider1") + new_role2.update_permission("can_edit_roles", "true") user_role = Role.find_by(name: "user", provider: "greenlight") user_role.priority = 3 @@ -483,7 +486,8 @@ describe AdminsController, type: :controller do end it "should fail to update if there is a duplicate name" do - new_role = Role.create(name: "test2", priority: 1, provider: "provider1", can_edit_roles: true) + new_role = Role.create(name: "test2", priority: 1, provider: "provider1") + new_role.update_permission("can_edit_roles", "true") @request.session[:user_id] = @admin.id @@ -494,7 +498,8 @@ describe AdminsController, type: :controller do end it "should update role permisions" do - new_role = Role.create(name: "test2", priority: 1, provider: "provider1", can_edit_roles: true) + new_role = Role.create(name: "test2", priority: 1, provider: "provider1") + new_role.update_permission("can_edit_roles", "true") @request.session[:user_id] = @admin.id @@ -503,10 +508,10 @@ describe AdminsController, type: :controller do new_role.reload expect(new_role.name).to eq("test") - expect(new_role.can_edit_roles).to eq(false) + expect(new_role.get_permission("can_edit_roles")).to eq(false) expect(new_role.colour).to eq("#45434") - expect(new_role.can_manage_users).to eq(true) - expect(new_role.send_promoted_email).to eq(false) + expect(new_role.get_permission("can_manage_users")).to eq(true) + expect(new_role.get_permission("send_promoted_email")).to eq(false) expect(response).to redirect_to admin_roles_path(selected_role: new_role.id) end end @@ -538,7 +543,8 @@ describe AdminsController, type: :controller do end it "should successfully delete the role" do - new_role = Role.create(name: "test2", priority: 1, provider: "provider1", can_edit_roles: true) + new_role = Role.create(name: "test2", priority: 1, provider: "provider1") + new_role.update_permission("can_edit_roles", "true") @request.session[:user_id] = @admin.id diff --git a/spec/controllers/rooms_controller_spec.rb b/spec/controllers/rooms_controller_spec.rb index 13856960..d2d7685f 100644 --- a/spec/controllers/rooms_controller_spec.rb +++ b/spec/controllers/rooms_controller_spec.rb @@ -66,7 +66,7 @@ describe RoomsController, type: :controller do it "should render cant_create_rooms if user doesn't have permission to create rooms" do user_role = @user.highest_priority_role - user_role.can_create_rooms = false + user_role.update_permission("can_create_rooms", "false") user_role.save! @request.session[:user_id] = @user.id diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 47db5ee6..21025cce 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -308,7 +308,7 @@ describe UsersController, type: :controller do user_role = user.highest_priority_role - user_role.can_manage_users = true + user_role.update_permission("can_manage_users", "true") user_role.save! @@ -331,7 +331,7 @@ describe UsersController, type: :controller do user_role = user.highest_priority_role - user_role.can_manage_users = true + user_role.update_permission("can_manage_users", "true") user_role.save! @@ -354,7 +354,8 @@ describe UsersController, type: :controller do @request.session[:user_id] = admin.id - tmp_role1 = Role.create(name: "test1", priority: 1, provider: "greenlight", send_promoted_email: true) + tmp_role1 = Role.create(name: "test1", priority: 1, provider: "greenlight") + tmp_role1.update_permission("send_promoted_email", "true") tmp_role2 = Role.create(name: "test2", priority: 2, provider: "greenlight") params = random_valid_user_params @@ -374,7 +375,8 @@ describe UsersController, type: :controller do admin.add_role :admin - tmp_role1 = Role.create(name: "test1", priority: 1, provider: "greenlight", send_demoted_email: true) + tmp_role1 = Role.create(name: "test1", priority: 1, provider: "greenlight") + tmp_role1.update_permission("send_demoted_email", "true") user.roles << tmp_role1 user.save! From d3b669d552a3731080712229609691fd00b2de91 Mon Sep 17 00:00:00 2001 From: farhatahmad <35435341+farhatahmad@users.noreply.github.com> Date: Wed, 28 Aug 2019 16:28:42 -0400 Subject: [PATCH 4/9] GRN2-xx: Users, Room and Recordings are now no longer permanently deleted (#773) * Bug fixes for 2.4 * Removed accidental code add * Switched from deleting to tombstoning * Fixed bug with login --- app/controllers/admins_controller.rb | 1 + app/controllers/rooms_controller.rb | 5 +-- app/controllers/sessions_controller.rb | 3 +- app/models/concerns/deleteable.rb | 45 +++++++++++++++++++ app/models/room.rb | 2 + app/models/user.rb | 2 + app/views/users/edit.html.erb | 9 ++++ .../20190822134205_create_role_permissions.rb | 13 +++--- .../20190828153347_add_deleted_column.rb | 10 +++++ db/schema.rb | 12 ++++- 10 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 app/models/concerns/deleteable.rb create mode 100644 db/migrate/20190828153347_add_deleted_column.rb diff --git a/app/controllers/admins_controller.rb b/app/controllers/admins_controller.rb index 1b52e585..41e7e9f8 100644 --- a/app/controllers/admins_controller.rb +++ b/app/controllers/admins_controller.rb @@ -195,6 +195,7 @@ class AdminsController < ApplicationController role.priority <= current_user.highest_priority_role.priority return redirect_to admin_roles_path(selected_role: role.id) else + role.role_permissions.delete_all role.delete end diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index e9e1b0c6..4283e46a 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -140,10 +140,7 @@ class RoomsController < ApplicationController # DELETE /:room_uid def destroy # Don't delete the users home room. - if @room.owned_by?(current_user) && @room != current_user.main_room - @room.destroy - delete_all_recordings(@room.bbb_id) - end + @room.destroy if @room.owned_by?(current_user) && @room != current_user.main_room redirect_to current_user.main_room end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 09eec68e..05a79fca 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -30,7 +30,6 @@ class SessionsController < ApplicationController def signin check_if_twitter_account - providers = configured_providers if one_provider provider_path = if Rails.configuration.omniauth_ldap ldap_signin_path @@ -147,6 +146,8 @@ class SessionsController < ApplicationController end def one_provider + providers = configured_providers + (!allow_user_signup? || !allow_greenlight_accounts?) && providers.count == 1 && !Rails.configuration.loadbalanced_configuration end diff --git a/app/models/concerns/deleteable.rb b/app/models/concerns/deleteable.rb new file mode 100644 index 00000000..a13985c9 --- /dev/null +++ b/app/models/concerns/deleteable.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/. +# +# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below). +# +# This program is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free Software +# Foundation; either version 3.0 of the License, or (at your option) any later +# version. +# +# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License along +# with BigBlueButton; if not, see . + +module Deleteable + extend ActiveSupport::Concern + + included do + # By default don't include deleted + default_scope { where(deleted: false) } + scope :include_deleted, -> { unscope(where: :deleted) } + scope :deleted, -> { include_deleted.where(deleted: true) } + end + + def destroy + run_callbacks :destroy + update_attribute(:deleted, true) + end + + def delete + destroy + end + + def undelete + assign_attributes(deleted: false) + end + + def undelete! + update_attribute(:deleted, false) + end +end diff --git a/app/models/room.rb b/app/models/room.rb index 23570167..0e61fa7e 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -19,6 +19,8 @@ require 'bbb_api' class Room < ApplicationRecord + include Deleteable + before_create :setup validates :name, presence: true diff --git a/app/models/user.rb b/app/models/user.rb index 52e39bbe..3ab10b23 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -19,6 +19,8 @@ require 'bbb_api' class User < ApplicationRecord + include Deleteable + attr_accessor :reset_token after_create :setup_user diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index 0c7eefdb..c0a86347 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -18,6 +18,15 @@
<%= render "users/components/menu_buttons" %> + + <% if @user.errors.any? %> +
<%= t("errors.title") %>:
+
    + <% @user.errors.full_messages.each do |err| %> +
  • <%= err %>.
  • + <% end %> +
+ <% end %>
<%= render "users/components/setting_view", setting_id: "account", setting_title: t("settings.account.subtitle") %> diff --git a/db/migrate/20190822134205_create_role_permissions.rb b/db/migrate/20190822134205_create_role_permissions.rb index ff29feb6..158f4ea5 100644 --- a/db/migrate/20190822134205_create_role_permissions.rb +++ b/db/migrate/20190822134205_create_role_permissions.rb @@ -21,11 +21,12 @@ class CreateRolePermissions < ActiveRecord::Migration[5.2] role.role_permissions.create(name: "can_manage_users", value: role.can_manage_users.to_s, enabled: true) end - remove_column :roles, :can_create_rooms - remove_column :roles, :send_promoted_email - remove_column :roles, :send_demoted_email - remove_column :roles, :can_edit_site_settings - remove_column :roles, :can_edit_roles - remove_column :roles, :can_manage_users + # Add these back in once the change to postgres is made + # remove_column :roles, :can_create_rooms + # remove_column :roles, :send_promoted_email + # remove_column :roles, :send_demoted_email + # remove_column :roles, :can_edit_site_settings + # remove_column :roles, :can_edit_roles + # remove_column :roles, :can_manage_users end end diff --git a/db/migrate/20190828153347_add_deleted_column.rb b/db/migrate/20190828153347_add_deleted_column.rb new file mode 100644 index 00000000..303fca99 --- /dev/null +++ b/db/migrate/20190828153347_add_deleted_column.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class AddDeletedColumn < ActiveRecord::Migration[5.2] + def change + add_column :users, :deleted, :boolean, null: false, default: false + add_index :users, :deleted + add_column :rooms, :deleted, :boolean, null: false, default: false + add_index :rooms, :deleted + end +end diff --git a/db/schema.rb b/db/schema.rb index 27dd362c..921e3f4e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_08_22_134205) do +ActiveRecord::Schema.define(version: 2019_08_28_153347) do create_table "features", force: :cascade do |t| t.integer "setting_id" @@ -46,6 +46,12 @@ ActiveRecord::Schema.define(version: 2019_08_22_134205) do create_table "roles", force: :cascade do |t| t.string "name" t.integer "priority", default: 9999 + t.boolean "can_create_rooms", default: false + t.boolean "send_promoted_email", default: false + t.boolean "send_demoted_email", default: false + t.boolean "can_edit_site_settings", default: false + t.boolean "can_edit_roles", default: false + t.boolean "can_manage_users", default: false t.string "colour" t.string "provider" t.datetime "created_at", null: false @@ -67,7 +73,9 @@ ActiveRecord::Schema.define(version: 2019_08_22_134205) do t.string "moderator_pw" t.string "attendee_pw" t.string "access_code" + t.boolean "deleted", default: false, null: false t.index ["bbb_id"], name: "index_rooms_on_bbb_id" + t.index ["deleted"], name: "index_rooms_on_deleted" t.index ["last_session"], name: "index_rooms_on_last_session" t.index ["name"], name: "index_rooms_on_name" t.index ["sessions"], name: "index_rooms_on_sessions" @@ -101,7 +109,9 @@ ActiveRecord::Schema.define(version: 2019_08_22_134205) do t.datetime "reset_sent_at" t.string "activation_digest" t.datetime "activated_at" + t.boolean "deleted", default: false, null: false t.index ["created_at"], name: "index_users_on_created_at" + t.index ["deleted"], name: "index_users_on_deleted" t.index ["email"], name: "index_users_on_email" t.index ["password_digest"], name: "index_users_on_password_digest", unique: true t.index ["provider"], name: "index_users_on_provider" From 666ee129888b1b391e4fdd6f18a47187ba1756b8 Mon Sep 17 00:00:00 2001 From: Ahmad Farhat Date: Fri, 30 Aug 2019 16:34:14 -0400 Subject: [PATCH 5/9] GRN2-xx: Cleaning up bugs that appeared after refactoring (#780) * First step * Fixed issues with update room --- app/assets/javascripts/rename.js | 2 +- app/controllers/concerns/authenticator.rb | 2 ++ app/controllers/rooms_controller.rb | 13 ++++++------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/rename.js b/app/assets/javascripts/rename.js index 49ddbce0..1631d9e1 100644 --- a/app/assets/javascripts/rename.js +++ b/app/assets/javascripts/rename.js @@ -123,7 +123,7 @@ $(document).on('turbolinks:load', function(){ if(element.is('#room-title')){ submit_update_request({ setting: "rename_header", - room_name: element.find('#user-text').text(), + name: element.find('#user-text').text(), }, element.data('path'), "POST"); } else if(element.is('#recording-title')){ diff --git a/app/controllers/concerns/authenticator.rb b/app/controllers/concerns/authenticator.rb index 3a8c1202..2fd6ded0 100644 --- a/app/controllers/concerns/authenticator.rb +++ b/app/controllers/concerns/authenticator.rb @@ -25,6 +25,8 @@ module Authenticator session[:user_id] = user.id + logger.info("Support: #{user.email} has successfully logged in.") + # If there are not terms, or the user has accepted them, check for email verification if !Rails.configuration.terms || user.accepted_terms check_email_verified(user) diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 4283e46a..313f27a7 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -187,19 +187,18 @@ class RoomsController < ApplicationController # POST /:room_uid/update_settings def update_settings begin - raise "Room name can't be blank" if room_params[:name].empty? + options = params[:room].nil? ? params : params[:room] + raise "Room name can't be blank" if options[:name].blank? raise "Unauthorized Request" if !@room.owned_by?(current_user) || @room == current_user.main_room # Update the rooms settings - if room_params - room_settings_string = create_room_settings_string(room_params) - @room.update_attributes(room_settings: room_settings_string) - end + room_settings_string = create_room_settings_string(options) + @room.update_attributes(room_settings: room_settings_string) if @room.room_settings != room_settings_string # Update the rooms name if it has been changed - @room.update_attributes(name: params[:room_name] || room_params[:name]) if @room.name != room_params[:name] + @room.update_attributes(name: options[:name]) if @room.name != options[:name] # Update the room's access code if it has changed - @room.update_attributes(access_code: room_params[:access_code]) if @room.access_code != room_params[:access_code] + @room.update_attributes(access_code: options[:access_code]) if @room.access_code != options[:access_code] flash[:success] = I18n.t("room.update_settings_success") rescue => e From 55d4a21dcb594c94211db5e13a2bf8848b59fbe8 Mon Sep 17 00:00:00 2001 From: Ahmad Farhat Date: Fri, 6 Sep 2019 11:49:30 -0400 Subject: [PATCH 6/9] Fixes after merge (#786) --- app/controllers/rooms_controller.rb | 27 ----------------------- spec/controllers/rooms_controller_spec.rb | 2 +- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 313f27a7..aae578de 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -75,36 +75,9 @@ class RoomsController < ApplicationController render :cant_create_rooms end else -<<<<<<< HEAD return redirect_to root_path, flash: { alert: I18n.t("room.invalid_provider") } if incorrect_user_domain - # Get users name - @name = if current_user - current_user.name - elsif cookies.encrypted[:greenlight_name] - cookies.encrypted[:greenlight_name] - else - "" - end - - @search, @order_column, @order_direction, pub_recs = - public_recordings(@room.bbb_id, params.permit(:search, :column, :direction), true) - - @pagy, @public_recordings = pagy_array(pub_recs) - - render :join - end - end - - # PATCH /:room_uid - def update - if params[:setting] == "rename_header" - update_room_attributes("name") - elsif params[:setting] == "rename_recording" - update_recording(params[:record_id], "meta_name" => params[:record_name]) -======= show_user_join ->>>>>>> GRN2-196: Fixed issues that scrutinizer is complaining about (#765) end end diff --git a/spec/controllers/rooms_controller_spec.rb b/spec/controllers/rooms_controller_spec.rb index d2d7685f..de2ec06e 100644 --- a/spec/controllers/rooms_controller_spec.rb +++ b/spec/controllers/rooms_controller_spec.rb @@ -126,7 +126,7 @@ describe RoomsController, type: :controller do it "redirects to root if the providers dont match" do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(true) - allow_any_instance_of(Room).to receive(:running?).and_return(false) + allow_any_instance_of(BbbServer).to receive(:room_running?).and_return(true) @owner.update_attribute(:provider, "provider1") @user.update_attribute(:provider, "provider2") From 7c6ad6d903054c235855973e7bd894fbc2cfec19 Mon Sep 17 00:00:00 2001 From: Ahmad Farhat Date: Fri, 6 Sep 2019 15:50:04 -0400 Subject: [PATCH 7/9] Improve code quality to increase scrut score (#789) --- app/assets/javascripts/main.js | 2 +- app/assets/javascripts/room.js | 149 +++++++++++++--------------- app/controllers/rooms_controller.rb | 28 +++--- 3 files changed, 83 insertions(+), 96 deletions(-) diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index dceefaa2..71eb2e74 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -33,7 +33,7 @@ function getLocalizedString(key) { }) // If key is not found, search the fallback language for the key - if (translated == undefined) { + if (translated === undefined) { translated = I18nFallback keyArr.forEach(function(k) { diff --git a/app/assets/javascripts/room.js b/app/assets/javascripts/room.js index f6fe3b27..d03fac8e 100644 --- a/app/assets/javascripts/room.js +++ b/app/assets/javascripts/room.js @@ -44,93 +44,82 @@ $(document).on('turbolinks:load', function(){ if ($("#cant-create-room-wrapper").length){ $(".wrapper").css('height', '100%').css('height', '-=130px'); } - } - // Display and update all fields related to creating a room in the createRoomModal - $("#create-room-block").click(function(){ - $("#create-room-name").val("") - $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) - $("#room_access_code").val(null) - - $("#createRoomModal form").attr("action", $("body").data('relative-root')) - $("#room_mute_on_join").prop("checked", false) - $("#room_require_moderator_approval").prop("checked", false) - $("#room_anyone_can_start").prop("checked", false) - $("#room_all_join_moderator").prop("checked", false) - - //show all elements & their children with a create-only class - $(".create-only").each(function() { - $(this).show() - if($(this).children().length > 0) { $(this).children().show() } + // Display and update all fields related to creating a room in the createRoomModal + $("#create-room-block").click(function(){ + showCreateRoom() }) - //hide all elements & their children with a update-only class - $(".update-only").each(function() { - $(this).attr('style',"display:none !important") - if($(this).children().length > 0) { $(this).children().attr('style',"display:none !important") } + // Display and update all fields related to creating a room in the createRoomModal + $(".update-room").click(function(){ + showUpdateRoom() }) - }) - - // Display and update all fields related to creating a room in the createRoomModal - $(".update-room").click(function(){ - var room_block_uid = $(this).closest("#room-block").data("room-uid") - $("#create-room-name").val($(this).closest("tbody").find("#room-name h4").text()) - $("#createRoomModal form").attr("action", room_block_uid + "/update_settings") - - //show all elements & their children with a update-only class - $(".update-only").each(function() { - $(this).show() - if($(this).children().length > 0) { $(this).children().show() } - }) - - //hide all elements & their children with a create-only class - $(".create-only").each(function() { - $(this).attr('style',"display:none !important") - if($(this).children().length > 0) { $(this).children().attr('style',"display:none !important") } - }) - - updateCurrentSettings($(this).closest("#room-block").data("room-settings")) - - accessCode = $(this).closest("#room-block").data("room-access-code") - - if(accessCode){ - $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code") + ": " + accessCode) - $("#room_access_code").val(accessCode) - } else{ - $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) - $("#room_access_code").val(null) - } - }) - - //Update the createRoomModal to show the correct current settings - function updateCurrentSettings(settings){ - //set checkbox - if(settings.muteOnStart){ - $("#room_mute_on_join").prop("checked", true) - } else { //default option - $("#room_mute_on_join").prop("checked", false) - } - - if(settings.requireModeratorApproval){ - $("#room_require_moderator_approval").prop("checked", true) - } else { //default option - $("#room_require_moderator_approval").prop("checked", false) - } - - if(settings.anyoneCanStart){ - $("#room_anyone_can_start").prop("checked", true) - } else { //default option - $("#room_anyone_can_start").prop("checked", false) - } - - if(settings.joinModerator){ - $("#room_all_join_moderator").prop("checked", true) - } else { //default option - $("#room_all_join_moderator").prop("checked", false) - } } }); +function showCreateRoom() { + $("#create-room-name").val("") + $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) + $("#room_access_code").val(null) + + $("#createRoomModal form").attr("action", $("body").data('relative-root')) + $("#room_mute_on_join").prop("checked", false) + $("#room_require_moderator_approval").prop("checked", false) + $("#room_anyone_can_start").prop("checked", false) + $("#room_all_join_moderator").prop("checked", false) + + //show all elements & their children with a create-only class + $(".create-only").each(function() { + $(this).show() + if($(this).children().length > 0) { $(this).children().show() } + }) + + //hide all elements & their children with a update-only class + $(".update-only").each(function() { + $(this).attr('style',"display:none !important") + if($(this).children().length > 0) { $(this).children().attr('style',"display:none !important") } + }) +} + +function showUpdateRoom() { + var room_block_uid = $(this).closest("#room-block").data("room-uid") + $("#create-room-name").val($(this).closest("tbody").find("#room-name h4").text()) + $("#createRoomModal form").attr("action", room_block_uid + "/update_settings") + + //show all elements & their children with a update-only class + $(".update-only").each(function() { + $(this).show() + if($(this).children().length > 0) { $(this).children().show() } + }) + + //hide all elements & their children with a create-only class + $(".create-only").each(function() { + $(this).attr('style',"display:none !important") + if($(this).children().length > 0) { $(this).children().attr('style',"display:none !important") } + }) + + updateCurrentSettings($(this).closest("#room-block").data("room-settings")) + + var accessCode = $(this).closest("#room-block").data("room-access-code") + + if(accessCode){ + $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code") + ": " + accessCode) + $("#room_access_code").val(accessCode) + } else { + $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) + $("#room_access_code").val(null) + } +} + +//Update the createRoomModal to show the correct current settings +function updateCurrentSettings(settings){ + //set checkbox + $("#room_mute_on_join").prop("checked", settings.muteOnStart) + $("#room_require_moderator_approval").prop("checked", settings.requireModeratorApproval) + $("#room_anyone_can_start").prop("checked", settings.anyoneCanStart) + $("#room_all_join_moderator").prop("checked", settings.joinModerator) +} + function generateAccessCode(){ const accessCodeLength = 6 var validCharacters = "0123456789" diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index aae578de..f4322537 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -141,7 +141,7 @@ class RoomsController < ApplicationController # Include the user's choices for the room settings room_settings = JSON.parse(@room[:room_settings]) - opts[:mute_on_start] = room_settings["muteOnStart"] if room_settings["muteOnStart"] + opts[:mute_on_start] = room_settings["muteOnStart"] opts[:require_moderator_approval] = room_settings["requireModeratorApproval"] begin @@ -164,14 +164,14 @@ class RoomsController < ApplicationController raise "Room name can't be blank" if options[:name].blank? raise "Unauthorized Request" if !@room.owned_by?(current_user) || @room == current_user.main_room - # Update the rooms settings + # Update the rooms values room_settings_string = create_room_settings_string(options) - @room.update_attributes(room_settings: room_settings_string) if @room.room_settings != room_settings_string - # Update the rooms name if it has been changed - @room.update_attributes(name: options[:name]) if @room.name != options[:name] - # Update the room's access code if it has changed - @room.update_attributes(access_code: options[:access_code]) if @room.access_code != options[:access_code] + @room.update_attributes( + name: options[:name], + room_settings: room_settings_string, + access_code: options[:access_code] + ) flash[:success] = I18n.t("room.update_settings_success") rescue => e @@ -202,14 +202,12 @@ class RoomsController < ApplicationController private def create_room_settings_string(options) - room_settings = {} - room_settings["muteOnStart"] = options[:mute_on_join] == "1" - - room_settings["requireModeratorApproval"] = options[:require_moderator_approval] == "1" - - room_settings["anyoneCanStart"] = options[:anyone_can_start] == "1" - - room_settings["joinModerator"] = options[:all_join_moderator] == "1" + room_settings = { + "muteOnStart": options[:mute_on_join] == "1", + "requireModeratorApproval": options[:require_moderator_approval] == "1", + "anyoneCanStart": options[:anyone_can_start] == "1", + "joinModerator": options[:all_join_moderator] == "1", + } room_settings.to_json end From e13e7623492740df361e951b9d6ec5104bc10f09 Mon Sep 17 00:00:00 2001 From: Ahmad Farhat Date: Thu, 12 Sep 2019 14:56:28 -0400 Subject: [PATCH 8/9] GRN2-243: Added a report issue button to the 500 error page (#796) * Added a report issue button to the 500 error page * Removed unused code * Removed unused quotes --- app/controllers/errors_controller.rb | 3 +- app/views/errors/greenlight_error.html.erb | 37 ++++++++++++---------- app/views/shared/_header.html.erb | 5 +++ config/application.rb | 2 ++ config/locales/en.yml | 1 + sample.env | 6 ++++ 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 3bea0915..365955d3 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -27,7 +27,8 @@ class ErrorsController < ApplicationController status_code: 500, message: I18n.t("errors.internal.message"), help: I18n.t("errors.internal.help"), - display_back: true + display_back: true, + report_issue: true } end diff --git a/app/views/errors/greenlight_error.html.erb b/app/views/errors/greenlight_error.html.erb index c7c83e74..0c75a78a 100644 --- a/app/views/errors/greenlight_error.html.erb +++ b/app/views/errors/greenlight_error.html.erb @@ -16,24 +16,29 @@
<% if defined?(status_code) %> - <%= status_code %> + <%= status_code %> <% else %> - 404 + 404 <% end %>
- <% if defined?(message) && defined?(help) %> -

<%= message %>

-

<%= help %>

- <% if defined?(display_back) && display_back %> - - <%= t("go_back") %> - - <% end %> - <% else %> -

<%= t("errors.not_found.message") %>

-

<%= t("errors.not_found.help") %>

- - <%= t("go_back") %> - + <% if defined?(message) && defined?(help) %> +

<%= message %>

+

<%= help %>

+ <% if defined?(display_back) && display_back %> + + <%= t("go_back") %> + <% end %> + <% if defined?(report_issue) && report_issue && Rails.configuration.report_issue_url.present? %> + + <%= t("errors.internal.report") %> + + <% end %> + <% else %> +

<%= t("errors.not_found.message") %>

+

<%= t("errors.not_found.help") %>

+ + <%= t("go_back") %> + + <% end %>
diff --git a/app/views/shared/_header.html.erb b/app/views/shared/_header.html.erb index 3ab6ce48..a563364c 100755 --- a/app/views/shared/_header.html.erb +++ b/app/views/shared/_header.html.erb @@ -76,6 +76,11 @@ <%= t("header.dropdown.help") %> + <% if Rails.configuration.report_issue_url.present? %> + + <%= t("errors.internal.report") %> + + <% end %> <%= link_to logout_path, class: "dropdown-item" do %> <%= t("header.dropdown.signout") %> <% end %> diff --git a/config/application.rb b/config/application.rb index 5d91cf18..ba49ce03 100644 --- a/config/application.rb +++ b/config/application.rb @@ -125,6 +125,8 @@ module Greenlight config.maintenance_window = ENV["MAINTENANCE_WINDOW"] config.maintenance_mode = ENV["MAINTENANCE_MODE"] == "true" + config.report_issue_url = ENV["REPORT_ISSUE_URL"] + # DEFAULTS # Default branding image if the user does not specify one diff --git a/config/locales/en.yml b/config/locales/en.yml index 0c5c68f2..0088c051 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -153,6 +153,7 @@ en: internal: message: Looks like something went wrong on our end. help: The error has been logged, we'll take a look! + report: Report Issue maintenance: message: Sorry, we're down for maintenance. help: We'll be back soon! diff --git a/sample.env b/sample.env index 7039efee..50cba33f 100644 --- a/sample.env +++ b/sample.env @@ -162,6 +162,12 @@ MAINTENANCE_MODE=false # Ex: MAINTENANCE_WINDOW=Friday August 18 6pm-10pm EST MAINTENANCE_WINDOW= +# The link to the Report an Issue button that appears on the 500 page and in the Account Dropdown +# +# Defaults to the Github Issues Page for Greenlight +# Button can be disabled by setting the value to blank +REPORT_ISSUE_URL=https://github.com/bigbluebutton/greenlight/issues/new + # Comment this out to send logs to STDOUT in production instead of log/production.log . # # RAILS_LOG_TO_STDOUT=true From 6d29422c31da49aa50b32fbf6624412c3361026c Mon Sep 17 00:00:00 2001 From: Ahmad Farhat Date: Fri, 20 Sep 2019 09:02:55 -0400 Subject: [PATCH 9/9] Default to EN if language is not recognized (#805) --- app/controllers/application_controller.rb | 9 ++++++++- spec/controllers/application_controller_spec.rb | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index cc8e01ec..96cd481f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -99,7 +99,14 @@ class ApplicationController < ActionController::Base else http_accept_language.language_region_compatible_from(I18n.available_locales) end - I18n.locale = locale.tr('-', '_') unless locale.nil? + + begin + I18n.locale = locale.tr('-', '_') unless locale.nil? + rescue + # Default to English if there are any issues in language + logger.error("Support: User locale is not supported (#{locale}") + I18n.locale = "en" + end end # Checks to make sure that the admin has changed his password from the default diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index ff05ea6d..49ac8192 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -80,6 +80,20 @@ describe ApplicationController do end end + context "setters" do + it "sets the user locale correctly" do + user = create(:user, language: "ru-RU") + + expect(controller.user_locale(user)).to eql("ru_RU") + end + + it "defaults to English locale if invalid language is set" do + user = create(:user, language: "ru") + + expect(controller.user_locale(user)).to eql("en") + end + end + context "allow_greenlight_accounts" do it "allows if user sign up is turned on" do allow(Rails.configuration).to receive(:loadbalanced_configuration).and_return(false)