diff --git a/.rubocop.yml b/.rubocop.yml index 9879483624..0e7a2d4fab 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -73,11 +73,11 @@ Style/RescueStandardError: Enabled: false # Align the elements of a hash literal if they span more than one line. -Layout/AlignHash: +Layout/HashAlignment: Enabled: false # Align the parameters of a method definition if they span more than one line. -Layout/AlignParameters: +Layout/ParameterAlignment: Enabled: false # Align ends corresponding to defs correctly. @@ -93,7 +93,7 @@ Layout/EmptyLineAfterGuardClause: Enabled: false # Align the arguments of a method call if they span more than one line. -Layout/AlignArguments: +Layout/ArgumentAlignment: Enabled: false # @@ -120,7 +120,7 @@ Metrics/ClassLength: Enabled: false # Limit lines to 80 characters. -Metrics/LineLength: +Layout/LineLength: Max: 130 # Avoid methods longer than 10 lines of code. @@ -141,5 +141,39 @@ Metrics/CyclomaticComplexity: Max: 17 # Checks for method parameter names that contain capital letters, end in numbers, or do not meet a minimal length. -Naming/UncommunicativeMethodParamName: - Enabled: false +Naming/MethodParameterName: + Enabled: false + +Lint/LiteralInInterpolation: + Enabled: false + +Layout/EmptyLinesAroundAttributeAccessor: + Enabled: true + +Layout/SpaceAroundMethodCallOperator: + Enabled: true + +Lint/DeprecatedOpenSSLConstant: + Enabled: true + +Lint/RaiseException: + Enabled: true + +Lint/StructNewOverride: + Enabled: true + +Style/ExponentialNotation: + Enabled: true + +Style/HashEachMethods: + Enabled: true + +Style/HashTransformKeys: + Enabled: true + +Style/HashTransformValues: + Enabled: true + +Style/SlicingWithRange: + Enabled: true + \ No newline at end of file diff --git a/Gemfile b/Gemfile index 8b4f23bc91..2fb63fb750 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ git_source(:github) do |repo_name| end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.2.3' +gem 'rails', '~> 5.2.4.3' # Use Puma as the app server gem 'puma', '~> 3.12' @@ -44,6 +44,8 @@ gem 'bcrypt', '~> 3.1.7' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.1.0', require: false +gem 'sprockets', '< 4.0.0' + # Authentication. gem 'omniauth' gem 'omniauth-twitter' diff --git a/Gemfile.lock b/Gemfile.lock index 6f13110959..97ab3ab0d7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,54 +9,54 @@ GIT GEM remote: https://rubygems.org/ specs: - action-cable-testing (0.5.0) + action-cable-testing (0.6.1) actioncable (>= 5.0) - actioncable (5.2.3) - actionpack (= 5.2.3) + actioncable (5.2.4.3) + actionpack (= 5.2.4.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.3) - actionpack (= 5.2.3) - actionview (= 5.2.3) - activejob (= 5.2.3) + actionmailer (5.2.4.3) + actionpack (= 5.2.4.3) + actionview (= 5.2.4.3) + activejob (= 5.2.4.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.3) - actionview (= 5.2.3) - activesupport (= 5.2.3) - rack (~> 2.0) + actionpack (5.2.4.3) + actionview (= 5.2.4.3) + activesupport (= 5.2.4.3) + rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.3) - activesupport (= 5.2.3) + actionview (5.2.4.3) + activesupport (= 5.2.4.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.3) - activesupport (= 5.2.3) + activejob (5.2.4.3) + activesupport (= 5.2.4.3) globalid (>= 0.3.6) - activemodel (5.2.3) - activesupport (= 5.2.3) - activerecord (5.2.3) - activemodel (= 5.2.3) - activesupport (= 5.2.3) + activemodel (5.2.4.3) + activesupport (= 5.2.4.3) + activerecord (5.2.4.3) + activemodel (= 5.2.4.3) + activesupport (= 5.2.4.3) arel (>= 9.0) - activestorage (5.2.3) - actionpack (= 5.2.3) - activerecord (= 5.2.3) + activestorage (5.2.4.3) + actionpack (= 5.2.4.3) + activerecord (= 5.2.4.3) marcel (~> 0.3.1) - activesupport (5.2.3) + activesupport (5.2.4.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) arel (9.0.0) ast (2.4.0) - autoprefixer-rails (9.6.1) + autoprefixer-rails (9.7.6) execjs bcrypt (3.1.13) bigbluebutton-api-ruby (1.7.0) @@ -64,14 +64,14 @@ GEM bindex (0.8.1) bn-ldap-authentication (0.1.2) net-ldap (~> 0) - bootsnap (1.4.4) + bootsnap (1.4.6) msgpack (~> 1.0) bootstrap (4.3.1) autoprefixer-rails (>= 9.1.0) popper_js (>= 1.14.3, < 2) sassc-rails (>= 2.0.0) - builder (3.2.3) - byebug (11.0.1) + builder (3.2.4) + byebug (11.1.3) cancancan (2.3.0) coffee-rails (4.2.2) coffee-script (>= 2.2.0) @@ -80,7 +80,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.5) + concurrent-ruby (1.1.6) coveralls (0.8.23) json (>= 1.8, < 3) simplecov (~> 0.16.1) @@ -89,46 +89,45 @@ GEM tins (~> 1.6) crack (0.4.3) safe_yaml (~> 1.0.0) - crass (1.0.5) + crass (1.0.6) diff-lcs (1.3) docile (1.3.2) - dotenv (2.7.4) - dotenv-rails (2.7.4) - dotenv (= 2.7.4) + dotenv (2.7.5) + dotenv-rails (2.7.5) + dotenv (= 2.7.5) railties (>= 3.2, < 6.1) - erubi (1.8.0) + erubi (1.9.0) execjs (2.7.0) - factory_bot (5.0.2) + factory_bot (5.2.0) activesupport (>= 4.2.0) - factory_bot_rails (5.0.2) - factory_bot (~> 5.0.2) + factory_bot_rails (5.2.0) + factory_bot (~> 5.2.0) railties (>= 4.2.0) - faker (1.9.6) - i18n (>= 0.7) - faraday (0.15.4) + faker (2.11.0) + i18n (>= 1.6, < 2) + faraday (1.0.1) multipart-post (>= 1.2, < 3) - ffi (1.11.1) + ffi (1.12.2) font-awesome-sass (5.9.0) sassc (>= 1.11) globalid (0.4.2) activesupport (>= 4.2.0) - hashdiff (0.4.0) - hashie (3.6.0) + hashdiff (1.0.1) + hashie (4.1.0) hiredis (0.6.3) http_accept_language (2.1.1) - i18n (1.6.0) + i18n (1.8.2) concurrent-ruby (~> 1.0) - i18n-language-mapping (0.1.1) - jaro_winkler (1.5.3) - jbuilder (2.9.1) - activesupport (>= 4.2.0) + i18n-language-mapping (0.1.2) + jbuilder (2.10.0) + activesupport (>= 5.0.0) jquery-rails (4.3.5) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) jquery-ui-rails (6.0.1) railties (>= 3.2.16) - json (2.2.0) + json (2.3.0) jwt (2.2.1) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) @@ -138,35 +137,35 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.3.1) + loofah (2.5.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) marcel (0.3.3) mimemagic (~> 0.3.2) - method_source (0.9.2) - mimemagic (0.3.3) + method_source (1.0.0) + mimemagic (0.3.5) mini_mime (1.0.2) mini_portile2 (2.4.0) - minitest (5.11.3) - msgpack (1.3.0) - multi_json (1.13.1) + minitest (5.14.1) + msgpack (1.3.3) + multi_json (1.14.1) multi_xml (0.6.0) multipart-post (2.1.1) - net-ldap (0.16.1) - nio4r (2.4.0) + net-ldap (0.16.2) + nio4r (2.5.2) nokogiri (1.10.9) mini_portile2 (~> 2.4.0) oauth (0.5.4) - oauth2 (1.4.1) - faraday (>= 0.8, < 0.16.0) + oauth2 (1.4.4) + faraday (>= 0.8, < 2.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - omniauth (1.9.0) - hashie (>= 3.4.6, < 3.7.0) + omniauth (1.9.1) + hashie (>= 3.4.6) rack (>= 1.6.2, < 3) omniauth-bn-launcher (0.1.3) omniauth (~> 1.3, >= 1.3.2) @@ -187,29 +186,29 @@ GEM omniauth-twitter (1.4.0) omniauth-oauth (~> 1.1) rack - pagy (3.3.2) - parallel (1.17.0) - parser (2.6.3.0) + pagy (3.8.1) + parallel (1.19.1) + parser (2.7.1.3) ast (~> 2.4.0) pg (0.21.0) - popper_js (1.14.5) - public_suffix (3.1.1) - puma (3.12.4) + popper_js (1.16.0) + public_suffix (4.0.5) + puma (3.12.6) rack (2.2.2) rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.3) - actioncable (= 5.2.3) - actionmailer (= 5.2.3) - actionpack (= 5.2.3) - actionview (= 5.2.3) - activejob (= 5.2.3) - activemodel (= 5.2.3) - activerecord (= 5.2.3) - activestorage (= 5.2.3) - activesupport (= 5.2.3) + rails (5.2.4.3) + actioncable (= 5.2.4.3) + actionmailer (= 5.2.4.3) + actionpack (= 5.2.4.3) + actionview (= 5.2.4.3) + activejob (= 5.2.4.3) + activemodel (= 5.2.4.3) + activerecord (= 5.2.4.3) + activestorage (= 5.2.4.3) + activesupport (= 5.2.4.3) bundler (>= 1.3.0) - railties (= 5.2.3) + railties (= 5.2.4.3) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.4) actionpack (>= 5.0.1.x) @@ -218,64 +217,67 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.2.3) - actionpack (= 5.2.3) - activesupport (= 5.2.3) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (5.2.4.3) + actionpack (= 5.2.4.3) + activesupport (= 5.2.4.3) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (13.0.1) random_password (0.1.1) - rb-fsevent (0.10.3) - rb-inotify (0.10.0) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) ffi (~> 1.0) - recaptcha (5.0.0) + recaptcha (5.5.0) json - redcarpet (3.4.0) - redis (4.1.2) + redcarpet (3.5.0) + redis (4.1.4) remote_syslog_logger (1.0.4) syslog_protocol - request_store (1.4.1) + request_store (1.5.0) rack (>= 1.4) - rspec-core (3.8.2) - rspec-support (~> 3.8.0) - rspec-expectations (3.8.4) + rexml (3.2.4) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-mocks (3.8.1) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.8.0) - rspec-rails (3.8.2) + rspec-support (~> 3.9.0) + rspec-rails (3.9.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.8.0) - rspec-expectations (~> 3.8.0) - rspec-mocks (~> 3.8.0) - rspec-support (~> 3.8.0) - rspec-support (3.8.2) - rubocop (0.72.0) - jaro_winkler (~> 1.5.1) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.3) + rubocop (0.84.0) parallel (~> 1.10) - parser (>= 2.6) + parser (>= 2.7.0.1) rainbow (>= 2.2.2, < 4.0) + rexml + rubocop-ast (>= 0.0.3) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.0.3) + parser (>= 2.7.0.1) ruby-progressbar (1.10.1) safe_yaml (1.0.5) - sassc (2.0.1) + sassc (2.3.0) ffi (~> 1.9) - rake sassc-rails (2.1.2) railties (>= 4.0.0) sassc (>= 2.0) sprockets (> 3.0) sprockets-rails tilt - sequel (5.29.0) + sequel (5.32.0) shoulda-matchers (3.1.3) activesupport (>= 4.0.0) simplecov (0.16.1) @@ -295,33 +297,35 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.13) + sync (0.5.0) syslog_protocol (0.9.2) term-ansicolor (1.7.1) tins (~> 1.0) - thor (0.20.3) + thor (1.0.1) thread_safe (0.3.6) - tilt (2.0.9) - tins (1.21.0) - turbolinks (5.2.0) + tilt (2.0.10) + tins (1.25.0) + sync + turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.5) + tzinfo (1.2.7) thread_safe (~> 0.1) - tzinfo-data (1.2019.3) + tzinfo-data (1.2020.1) tzinfo (>= 1.0.0) - uglifier (4.1.20) + uglifier (4.2.0) execjs (>= 0.3.0, < 3) - unicode-display_width (1.6.0) + unicode-display_width (1.7.0) web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) bindex (>= 0.4.0) railties (>= 5.0) - webmock (3.6.0) + webmock (3.8.3) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - websocket-driver (0.7.1) + websocket-driver (0.7.2) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) xml-simple (1.1.5) @@ -361,7 +365,7 @@ DEPENDENCIES pagy pg (~> 0.18) puma (~> 3.12) - rails (~> 5.2.3) + rails (~> 5.2.4.3) rails-controller-testing random_password recaptcha @@ -375,6 +379,7 @@ DEPENDENCIES shoulda-matchers (~> 3.1) spring spring-watcher-listen (~> 2.0.0) + sprockets (< 4.0.0) sqlite3 (~> 1.3.6) tabler-rubygem! turbolinks (~> 5) diff --git a/app/assets/javascripts/admins.js b/app/assets/javascripts/admins.js index 53fcfb571b..f2db3fe804 100644 --- a/app/assets/javascripts/admins.js +++ b/app/assets/javascripts/admins.js @@ -80,7 +80,7 @@ $(document).on('turbolinks:load', function(){ // Get the uid of the selected user let user = $(".selectpicker").selectpicker('val') if (user != "") { - userInfo = JSON.parse(user) + let userInfo = JSON.parse(user) $("#merge-from").html("" + userInfo.name + "" + "" + userInfo.email + "" + "" + userInfo.uid + "") } }) @@ -95,7 +95,7 @@ $(document).on('turbolinks:load', function(){ }) // Updates the colour picker to the correct colour - role_colour = $("#role-colorinput-regular").data("colour") + let role_colour = $("#role-colorinput-regular").data("colour") $("#role-colorinput-regular").css("background-color", role_colour); $("#role-colorinput-regular").css("border-color", role_colour); @@ -122,6 +122,18 @@ function changeBrandingImage(path) { $.post(path, {value: url}) } +// Change the Legal URL to the one provided +function changeLegalURL(path) { + var url = $("#legal-url").val() + $.post(path, {value: url}) +} + +// Change the Privacy Policy URL to the one provided +function changePrivacyPolicyURL(path) { + var url = $("#privpolicy-url").val() + $.post(path, {value: url}) +} + function mergeUsers() { let userToMerge = $("#from-uid").text() $.post($("#merge-save-access").data("path"), {merge: userToMerge}) @@ -263,4 +275,4 @@ function loadRoleColourSelector(role_colour, disabled) { $("#role-colour").val(color.toHEXA().toString()); }); } -} \ No newline at end of file +} diff --git a/app/assets/javascripts/room.js b/app/assets/javascripts/room.js index 6186aacade..8137d0c6d7 100644 --- a/app/assets/javascripts/room.js +++ b/app/assets/javascripts/room.js @@ -44,11 +44,6 @@ $(document).on('turbolinks:load', function(){ } }); - // Forces the wrapper to take the entire screen height if the user can't create rooms - 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(){ showCreateRoom(this) @@ -138,7 +133,6 @@ $(document).on('turbolinks:load', function(){ }); function showCreateRoom(target) { - var modal = $(target) $("#create-room-name").val("") $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) $("#room_access_code").val(null) @@ -269,4 +263,4 @@ function removeSharedUser(target) { parentLI.removeChild(target) parentLI.classList.add("remove-shared") } -} \ No newline at end of file +} diff --git a/app/assets/javascripts/user_edit.js b/app/assets/javascripts/user_edit.js index e1dee271ef..eca04cb29c 100644 --- a/app/assets/javascripts/user_edit.js +++ b/app/assets/javascripts/user_edit.js @@ -18,61 +18,19 @@ $(document).on('turbolinks:load', function(){ var controller = $("body").data('controller'); var action = $("body").data('action'); if ((controller == "admins" && action == "edit_user") || (controller == "users" && action == "edit")) { - // Clear the role when the user clicks the x - $(".clear-role").click(clearRole) - - // When the user selects an item in the dropdown add the role to the user - $("#role-select-dropdown").change(function(data){ - var dropdown = $("#role-select-dropdown"); - var select_role_id = dropdown.val(); - - if(select_role_id){ - // Disable the role in the dropdown - var selected_role = dropdown.find('[value=\"' + select_role_id + '\"]'); - selected_role.prop("disabled", true) - - // Add the role tag - var tag_container = $("#role-tag-container"); - tag_container.append("" + - selected_role.text() + ""); - - // Update the role ids input that gets submited on user update - var role_ids = $("#user_role_ids").val() - role_ids += " " + select_role_id - $("#user_role_ids").val(role_ids) - - // Add the clear role function to the tag - $("#user-role-tag_" + select_role_id).click(clearRole); - - // Reset the dropdown - dropdown.val(null) - } + // Hack to make it play nice with turbolinks + if ($("#role-dropdown:visible").length == 0){ + $(window).trigger('load.bs.select.data-api') + } + + // Check to see if the role dropdown was set up + if ($("#role-dropdown").length != 0){ + $("#role-dropdown").selectpicker('val', $("#user_role_id").val()) + } + + // Update hidden field with new value + $("#role-dropdown").on("changed.bs.select", function(){ + $("#user_role_id").val($("#role-dropdown").selectpicker('val')) }) } -}) - -// This function removes the specfied role from a user -function clearRole(data){ - // Get the role id - var role_id = $(data.target).data("role-id"); - var role_tag = $("#user-role-tag_" + role_id); - - // Remove the role tag - $(role_tag).remove() - - // Update the role ids input - var role_ids = $("#user_role_ids").val() - var parsed_ids = role_ids.split(' ') - - var index = parsed_ids.indexOf(role_id.toString()); - - if (index > -1) { - parsed_ids.splice(index, 1); - } - - $("#user_role_ids").val(parsed_ids.join(' ')) - - // Enable the role in the role select dropdown - var selected_role = $("#role-select-dropdown").find('[value=\"' + role_id + '\"]'); - selected_role.prop("disabled", false) -} \ No newline at end of file +}) \ No newline at end of file diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss index 8809beb0a0..15cce7003e 100755 --- a/app/assets/stylesheets/main.scss +++ b/app/assets/stylesheets/main.scss @@ -158,3 +158,10 @@ .signin-button { font-size: 16px; } + +.table-responsive tbody td:first-child > *:first-child { + max-height: 3em; + overflow: hidden; + max-width: 200px; + display: flex; +} diff --git a/app/controllers/admins_controller.rb b/app/controllers/admins_controller.rb index be8e80900b..577162b8e0 100644 --- a/app/controllers/admins_controller.rb +++ b/app/controllers/admins_controller.rb @@ -63,10 +63,17 @@ def server_recordings # GET /admins/rooms def server_rooms @search = params[:search] || "" - @order_column = params[:column] && params[:direction] != "none" ? params[:column] : "created_at" + @order_column = params[:column] && params[:direction] != "none" ? params[:column] : "status" @order_direction = params[:direction] && params[:direction] != "none" ? params[:direction] : "DESC" - @running_room_bbb_ids = all_running_meetings[:meetings].pluck(:meetingID) + meetings = all_running_meetings[:meetings] + @order_column = "created_at" if meetings.empty? + @running_room_bbb_ids = meetings.pluck(:meetingID) + + @participants_count = {} + meetings.each do |meet| + @participants_count[meet[:meetingID]] = meet[:participantCount] + end @user_list = shared_user_list if shared_access_allowed @@ -86,23 +93,21 @@ def edit_user # POST /admins/ban/:user_uid def ban_user - @user.roles = [] - @user.add_role :denied + @user.set_role :denied redirect_back fallback_location: admins_path, flash: { success: I18n.t("administrator.flash.banned") } end # POST /admins/unban/:user_uid def unban_user - @user.remove_role :denied - @user.add_role :user + @user.set_role :user redirect_back fallback_location: admins_path, flash: { success: I18n.t("administrator.flash.unbanned") } end # POST /admins/approve/:user_uid def approve - @user.remove_role :pending + @user.set_role :user send_user_approved_email(@user) @@ -298,7 +303,7 @@ def delete_role flash[:alert] = I18n.t("administrator.roles.role_has_users", user_count: role.users.count) return redirect_to admin_roles_path(selected_role: role.id) elsif Role::RESERVED_ROLE_NAMES.include?(role) || role.provider != @user_domain || - role.priority <= current_user.highest_priority_role.priority + role.priority <= current_user.role.priority return redirect_to admin_roles_path(selected_role: role.id) else role.role_permissions.delete_all diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d59a64b98d..e9e78cfdd1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -27,7 +27,7 @@ class ApplicationController < ActionController::Base # Retrieves the current user. def current_user - @current_user ||= User.includes(:roles, :main_room).find_by(id: session[:user_id]) + @current_user ||= User.includes(:role, :main_room).find_by(id: session[:user_id]) if Rails.configuration.loadbalanced_configuration if @current_user && !@current_user.has_role?(:super_admin) && @@ -119,7 +119,7 @@ def check_admin_password 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 + edit_link: change_password_path(user_uid: current_user.uid)).html_safe end end diff --git a/app/controllers/concerns/authenticator.rb b/app/controllers/concerns/authenticator.rb index f935d6b4c9..b2802da791 100644 --- a/app/controllers/concerns/authenticator.rb +++ b/app/controllers/concerns/authenticator.rb @@ -46,8 +46,10 @@ def check_email_verified(user) internal_error_url, not_found_url] url = if cookies[:return_to] && !dont_redirect_to.include?(cookies[:return_to]) cookies[:return_to] - else + elsif user.role.get_permission("can_create_rooms") user.main_room + else + cant_create_rooms_path end # Delete the cookie if it exists diff --git a/app/controllers/concerns/bbb_server.rb b/app/controllers/concerns/bbb_server.rb index ee70ed7c76..f8a99a566a 100644 --- a/app/controllers/concerns/bbb_server.rb +++ b/app/controllers/concerns/bbb_server.rb @@ -54,7 +54,6 @@ def join_path(room, name, options = {}, uid = nil) 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 diff --git a/app/controllers/concerns/emailer.rb b/app/controllers/concerns/emailer.rb index 59540023b4..aeb48b1df4 100644 --- a/app/controllers/concerns/emailer.rb +++ b/app/controllers/concerns/emailer.rb @@ -99,7 +99,6 @@ def send_user_approved_email(user) def send_approval_user_signup_email(user) begin return unless Rails.configuration.enable_email_verification - admin_emails = admin_emails() UserMailer.approval_user_signup(user, admins_url(tab: "pending"), admin_emails, @settings).deliver_now unless admin_emails.empty? @@ -129,12 +128,12 @@ def user_verification_link(token) end def admin_emails - admins = User.all_users_with_roles.where(roles: { role_permissions: { name: "can_manage_users", value: "true" } }) + roles = Role.where(provider: @user_domain, role_permissions: { name: "can_manage_users", value: "true" }) + .pluck(:name) - if Rails.configuration.loadbalanced_configuration - admins = admins.without_role(:super_admin) - .where(provider: @user_domain) - end + admins = User.with_role(roles - ["super_admin"]) + + admins = admins.where(provider: @user_domain) if Rails.configuration.loadbalanced_configuration admins.collect(&:email).join(",") end diff --git a/app/controllers/concerns/populator.rb b/app/controllers/concerns/populator.rb index 771fa25e2b..79b7272471 100644 --- a/app/controllers/concerns/populator.rb +++ b/app/controllers/concerns/populator.rb @@ -25,29 +25,22 @@ def manage_users_list initial_user = case @tab when "active" - User.includes(:roles).without_role(:pending).without_role(:denied) + User.without_role([:pending, :denied]) when "deleted" - User.includes(:roles).deleted + User.deleted else - User.includes(:roles) + User.all end current_role = Role.find_by(name: @tab, provider: @user_domain) if @tab == "pending" || @tab == "denied" - initial_list = if current_user.has_role? :super_admin - initial_user.where.not(id: current_user.id) - else - initial_user.without_role(:super_admin).where.not(id: current_user.id) - end + initial_list = initial_user.without_role(:super_admin) unless current_user.has_role? :super_admin - if Rails.configuration.loadbalanced_configuration - initial_list.where(provider: @user_domain) - .admins_search(@search, current_role) - .admins_order(@order_column, @order_direction) - else - initial_list.admins_search(@search, current_role) - .admins_order(@order_column, @order_direction) - end + initial_list = initial_list.where(provider: @user_domain) if Rails.configuration.loadbalanced_configuration + + initial_list.where.not(id: current_user.id) + .admins_search(@search, current_role) + .admins_order(@order_column, @order_direction) end # Returns a list of rooms that are in the same context of the current user @@ -55,9 +48,9 @@ def server_rooms_list if Rails.configuration.loadbalanced_configuration Room.includes(:owner).where(users: { provider: @user_domain }) .admins_search(@search) - .admins_order(@order_column, @order_direction) + .admins_order(@order_column, @order_direction, @running_room_bbb_ids) else - Room.includes(:owner).all.admins_search(@search).admins_order(@order_column, @order_direction) + Room.includes(:owner).admins_search(@search).admins_order(@order_column, @order_direction, @running_room_bbb_ids) end end @@ -77,10 +70,7 @@ def shared_user_list roles_can_appear << role.name if role.get_permission("can_appear_in_share_list") && role.priority >= 0 end - initial_list = User.where.not(uid: current_user.uid) - .without_role(:pending) - .without_role(:denied) - .with_highest_priority_role(roles_can_appear) + initial_list = User.where.not(uid: current_user.uid).with_role(roles_can_appear) return initial_list unless Rails.configuration.loadbalanced_configuration initial_list.where(provider: @user_domain) @@ -88,7 +78,7 @@ def shared_user_list # Returns a list of users that can merged into another user def merge_user_list - initial_list = User.where.not(uid: current_user.uid).without_role(:super_admin) + initial_list = User.without_role(:super_admin).where.not(uid: current_user.uid) return initial_list unless Rails.configuration.loadbalanced_configuration initial_list.where(provider: @user_domain) diff --git a/app/controllers/concerns/rolify.rb b/app/controllers/concerns/rolify.rb index 0dfff42870..63eca96e5e 100644 --- a/app/controllers/concerns/rolify.rb +++ b/app/controllers/concerns/rolify.rb @@ -46,60 +46,23 @@ def create_role(new_role_name) 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.get_permission("can_manage_users") + def update_roles(role_id) + return true if role_id.blank? + # Check to make sure user can edit roles + return false unless current_user.role.get_permission("can_manage_users") - new_roles = roles.split(' ').map(&:to_i) - old_roles = @user.roles.pluck(:id).uniq + return true if @user.role_id == role_id.to_i - added_role_ids = new_roles - old_roles - removed_role_ids = old_roles - new_roles + new_role = Role.find_by(id: role_id, provider: @user_domain) + # Return false if new role doesn't exist + return false if new_role.nil? - 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 + return false if new_role.priority < current_user.role.priority # Send promoted/demoted emails - 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) - @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? + send_user_promoted_email(@user, new_role) if new_role.get_permission("send_promoted_email") - @user.save! + @user.update_attribute(:role_id, role_id) end # Updates a roles priority @@ -107,7 +70,7 @@ 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 + current_user_role = current_user.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) @@ -149,7 +112,7 @@ def update_priority(role_to_update) # Update Permissions def update_permissions(role) - current_user_role = current_user.highest_priority_role + current_user_role = current_user.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 diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb index 36a84c8334..73ea364acd 100644 --- a/app/controllers/password_resets_controller.rb +++ b/app/controllers/password_resets_controller.rb @@ -67,6 +67,8 @@ def update def find_user @user = User.find_by(reset_digest: User.hash_token(params[:id]), provider: @user_domain) + + return redirect_to new_password_reset_url, alert: I18n.t("reset_password.invalid_token") unless @user end def user_params diff --git a/app/controllers/recordings_controller.rb b/app/controllers/recordings_controller.rb index fc82470e0f..93912b4679 100644 --- a/app/controllers/recordings_controller.rb +++ b/app/controllers/recordings_controller.rb @@ -57,8 +57,6 @@ def find_room # Ensure the user is logged into the room they are accessing. def verify_room_ownership - if !@room.owned_by?(current_user) && !current_user&.highest_priority_role&.get_permission("can_manage_rooms_recordings") - redirect_to root_path - end + redirect_to root_path if !@room.owned_by?(current_user) && !current_user&.role&.get_permission("can_manage_rooms_recordings") end end diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 7d2d048b45..c9ef641787 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -25,7 +25,7 @@ class RoomsController < ApplicationController 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 :find_room, except: [:create, :join_specific_room, :cant_create_rooms] before_action :verify_room_ownership_or_admin_or_shared, only: [:start, :shared_access] before_action :verify_room_ownership_or_admin, only: [:update_settings, :destroy] before_action :verify_room_ownership_or_shared, only: [:remove_shared_access] @@ -69,19 +69,13 @@ def show # If its the current user's room if current_user && (@room.owned_by?(current_user) || @shared_room) - 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) - - @user_list = shared_user_list if shared_access_allowed - - @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 + # User is allowed to have rooms + @search, @order_column, @order_direction, recs = + recordings(@room.bbb_id, params.permit(:search, :column, :direction), true) + + @user_list = shared_user_list if shared_access_allowed + + @pagy, @recordings = pagy_array(recs) else return redirect_to root_path, flash: { alert: I18n.t("room.invalid_provider") } if incorrect_user_domain @@ -89,6 +83,19 @@ def show end end + # GET /rooms + def cant_create_rooms + shared_rooms = current_user.shared_rooms + + if current_user.shared_rooms.empty? + # 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 + else + redirect_to shared_rooms[0] + end + end + # POST /:room_uid def join return redirect_to root_path, diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 0325b2773e..3883c0478d 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -39,7 +39,7 @@ def signin "#{Rails.configuration.relative_url_root}/auth/#{@providers.first}" end - return redirect_to provider_path + redirect_to provider_path end end @@ -94,7 +94,7 @@ def create login(user) end - # GET /users/logout + # POST /users/logout def destroy logout redirect_to root_path @@ -218,7 +218,7 @@ def process_signin # Add pending role if approval method and is a new user if approval_registration && !@user_exists && @auth['provider'] != :ldap - user.add_role :pending + user.set_role :pending # Inform admins that a user signed up if emails are turned on send_approval_user_signup_email(user) @@ -228,6 +228,8 @@ def process_signin send_invite_user_signup_email(user) if invite_registration && !@user_exists + user.set_role :user unless @user_exists + login(user) if @auth['provider'] == "twitter" diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9ce870bb13..a061f246d0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -24,7 +24,7 @@ class UsersController < ApplicationController include Recorder include Rolify - before_action :find_user, only: [:edit, :change_password, :delete_account, :update] + before_action :find_user, only: [:edit, :change_password, :delete_account, :update, :update_password] 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] @@ -47,7 +47,7 @@ def create # Set user to pending and redirect if Approval Registration is set if approval_registration - @user.add_role :pending + @user.set_role :pending return redirect_to root_path, flash: { success: I18n.t("registration.approval.signup") } unless Rails.configuration.enable_email_verification @@ -56,7 +56,11 @@ def create 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 + if !Rails.configuration.enable_email_verification || @user.email_verified + @user.set_role :user + + login(@user) && return + end send_activation_email(@user, @user.create_activation_token) @@ -77,9 +81,8 @@ def change_password def delete_account end - # PATCH /u/:user_uid/edit + # POST /u/:user_uid/edit def update - profile = params[:setting] == "password" ? change_password_path(@user) : edit_user_path(@user) if session[:prev_url].present? path = session[:prev_url] session.delete(:prev_url) @@ -87,44 +90,50 @@ def update path = admins_path end - redirect_path = current_user.admin_of?(@user, "can_manage_users") ? path : profile + redirect_path = current_user.admin_of?(@user, "can_manage_users") ? path : edit_user_path(@user) - if params[:setting] == "password" - # Update the users password. + unless @user.greenlight_account? + params[:user][:name] = @user.name + params[:user][:email] = @user.email + end - if @user.authenticate(user_params[:password]) - # Verify that the new passwords match. - if user_params[:new_password] == user_params[:password_confirmation] - @user.password = user_params[:new_password] - else - # New passwords don't match. - @user.errors.add(:password_confirmation, "doesn't match") - end + 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_id]) + return redirect_to redirect_path, flash: { success: I18n.t("info_update_success") } else - # Original password is incorrect, can't update. - @user.errors.add(:password, "is incorrect") + flash[:alert] = I18n.t("administrator.roles.invalid_assignment") end + 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 :edit + end - render :change_password + # POST /u/:user_uid/change_password + def update_password + # Update the users password. + if @user.authenticate(user_params[:password]) + # Verify that the new passwords match. + if user_params[:new_password] == user_params[:password_confirmation] + @user.password = user_params[:new_password] + else + # New passwords don't match. + @user.errors.add(:password_confirmation, "doesn't match") + end else - if @user.update_attributes(user_params) - @user.update_attributes(email_verified: false) if user_params[:email] != @user.email + # Original password is incorrect, can't update. + @user.errors.add(:password, "is incorrect") + end - user_locale(@user) + # Notify the user that their account has been updated. + return redirect_to change_password_path, + flash: { success: I18n.t("info_update_success") } if @user.errors.empty? && @user.save - 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 - end + # redirect_to change_password_path + render :change_password end # DELETE /u/:user_uid diff --git a/app/helpers/admins_helper.rb b/app/helpers/admins_helper.rb index 6976a66b52..4761332068 100644 --- a/app/helpers/admins_helper.rb +++ b/app/helpers/admins_helper.rb @@ -31,6 +31,13 @@ def room_is_running(id) @running_room_bbb_ids.include?(id) end + # Returns a more friendly/readable date time object + def friendly_time(date) + return "" if date.nil? # Handle invalid dates + + I18n.l date, format: "%B %d, %Y %H:%M UTC" + end + # Site Settings def admin_invite_registration @@ -110,6 +117,6 @@ def room_configuration_string(name) # Roles def edit_disabled - @edit_disabled ||= @selected_role.priority <= current_user.highest_priority_role.priority + @edit_disabled ||= @selected_role.priority <= current_user.role.priority end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index eaf90a23c8..7b4e914b1d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -58,7 +58,16 @@ def fallback_translations # Returns the page that the logo redirects to when clicked on def home_page return admins_path if current_user.has_role? :super_admin - current_user.main_room + return current_user.main_room if current_user.role.get_permission("can_create_rooms") + cant_create_rooms_path + end + + # Returns 'active' if the current page is the users home page (used to style header) + def active_home + home_actions = %w[show cant_create_rooms] + return "active" if params[:controller] == "admins" && params[:action] == "index" && current_user.has_role?(:super_admin) + return "active" if params[:controller] == "rooms" && home_actions.include?(params[:action]) + "" end # Returns the action method of the current page @@ -97,10 +106,22 @@ def google_analytics_url "https://www.googletagmanager.com/gtag/js?id=#{ENV['GOOGLE_ANALYTICS_TRACKING_ID']}" end + # Checks to make sure the image url returns 200 and is of type image def valid_url?(input) - uri = URI.parse(input) - !uri.host.nil? - rescue URI::InvalidURIError + url = URI.parse(input) + + # Don't allow reference to own site + return false if url.host == request.host + + # Make a GET request and validate content type + http = Net::HTTP.new(url.host, url.port) + http.use_ssl = (url.scheme == "https") + + http.start do |web| + response = web.head(url.request_uri) + return response.code == "200" && response['Content-Type'].start_with?('image') + end + rescue false end end diff --git a/app/helpers/theming_helper.rb b/app/helpers/theming_helper.rb index bb725f12a4..527dd260ce 100644 --- a/app/helpers/theming_helper.rb +++ b/app/helpers/theming_helper.rb @@ -22,6 +22,16 @@ def logo_image @settings.get_value("Branding Image") || Rails.configuration.branding_image_default end + # Returns the legal URL based on user's provider + def legal_url + @settings.get_value("Legal URL") || "" + end + + # Returns the logo based on user's provider + def privpolicy_url + @settings.get_value("Privacy Policy URL") || "" + end + # Returns the primary color based on user's provider def user_color @settings.get_value("Primary Color") || Rails.configuration.primary_color_default diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index c92ce09b15..6e49a9a99d 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -26,7 +26,7 @@ def recaptcha_enabled? end def disabled_roles(user) - current_user_role = current_user.highest_priority_role + current_user_role = current_user.role # Admins are able to remove the admin role from other admins # For all other roles they can only add/remove roles with a higher priority @@ -38,7 +38,7 @@ def disabled_roles(user) .pluck(:id) end - user.roles.by_priority.pluck(:id) | disallowed_roles + [user.role.id] + disallowed_roles end # Returns language selection options for user edit @@ -52,6 +52,11 @@ def language_options language_opts.sort end + # Returns a list of roles that the user can have + def role_options + Role.editable_roles(@user_domain).where("priority >= ?", current_user.role.priority) + end + # Parses markdown for rendering. def markdown(text) markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, diff --git a/app/models/ability.rb b/app/models/ability.rb index 559d69f5be..be4391056e 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -25,7 +25,7 @@ def initialize(user) elsif user.has_role? :super_admin can :manage, :all else - highest_role = user.highest_priority_role + highest_role = user.role if highest_role.get_permission("can_edit_site_settings") can [:site_settings, :room_configuration, :update_settings, :update_room_configuration, :coloring, :registration_method], :admin diff --git a/app/models/concerns/auth_values.rb b/app/models/concerns/auth_values.rb index 0201959ce0..a3f719db52 100644 --- a/app/models/concerns/auth_values.rb +++ b/app/models/concerns/auth_values.rb @@ -63,7 +63,7 @@ def auth_roles(user, auth) role_provider = auth['provider'] == "bn_launcher" ? auth['info']['customer'] : "greenlight" roles.each do |role_name| role = Role.find_by(provider: role_provider, name: role_name) - user.roles << role if !role.nil? && !user.has_role?(role_name) + user.role = role if !role.nil? && !user.has_role?(role_name) end end end diff --git a/app/models/role.rb b/app/models/role.rb index 124bcd8e30..41c54bcf77 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -17,10 +17,12 @@ # with BigBlueButton; if not, see . class Role < ApplicationRecord - has_and_belongs_to_many :users, join_table: :users_roles + has_and_belongs_to_many :users, join_table: :users_roles # Obsolete -- not used anymore has_many :role_permissions - default_scope { includes(:role_permissions).order(:priority) } + has_many :users + + default_scope { includes(:role_permissions).distinct.order(:priority) } scope :by_priority, -> { order(:priority) } scope :editable_roles, ->(provider) { where(provider: provider).where.not(name: %w[super_admin denied pending]) } diff --git a/app/models/room.rb b/app/models/room.rb index e657fd12f1..02d0b7cc89 100644 --- a/app/models/room.rb +++ b/app/models/room.rb @@ -45,10 +45,13 @@ def self.admins_search(string) where(search_query, search: search_param) end - def self.admins_order(column, direction) + def self.admins_order(column, direction, running_ids) # Include the owner of the table table = joins(:owner) + # Rely on manual ordering if trying to sort by status + return order_by_status(table, running_ids) if column == "status" + return table.order(Arel.sql("rooms.#{column} #{direction}")) if table.column_names.include?(column) return table.order(Arel.sql("#{column} #{direction}")) if column == "users.name" @@ -80,6 +83,21 @@ def notify_waiting ActionCable.server.broadcast("#{uid}_waiting_channel", action: "started") end + # Return table with the running rooms first + def self.order_by_status(table, ids) + return table if ids.blank? + + order_string = "CASE bbb_id " + + ids.each_with_index do |id, index| + order_string += "WHEN '#{id}' THEN #{index} " + end + + order_string += "ELSE #{ids.length} END" + + table.order(Arel.sql(order_string)) + end + private # Generates a uid for the room and BigBlueButton. @@ -90,21 +108,18 @@ def setup self.attendee_pw = RandomPassword.generate(length: 12) 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) - (0...3).map { charset.to_a[rand(charset.size)] }.join - end - - # Generates a random room uid that uses the users name. + # Generates a fully random room uid. def random_room_uid - [owner.name_chunk, uid_chunk, uid_chunk].join('-').downcase + # 6 character long random string of chars from a..z and 0..9 + full_chunk = SecureRandom.alphanumeric(6).downcase + + [owner.name_chunk, full_chunk[0..2], full_chunk[3..5]].join("-") end # Generates a unique bbb_id based on uuid. def unique_bbb_id loop do - bbb_id = SecureRandom.hex(20) + bbb_id = SecureRandom.alphanumeric(40).downcase break bbb_id unless Room.exists?(bbb_id: bbb_id) end end diff --git a/app/models/setting.rb b/app/models/setting.rb index e38ee03685..38b0a9b4b0 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -48,6 +48,10 @@ def default_value(name) case name when "Branding Image" Rails.configuration.branding_image_default + when "Legal URL" + nil + when "Privacy Policy URL" + nil when "Primary Color" Rails.configuration.primary_color_default when "Registration Method" diff --git a/app/models/user.rb b/app/models/user.rb index bdc25fa019..fd02bc974c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -31,7 +31,9 @@ class User < ApplicationRecord has_many :shared_access 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, join_table: :users_roles # obsolete + + belongs_to :role, required: false validates :name, length: { maximum: 256 }, presence: true validates :provider, presence: true @@ -92,14 +94,12 @@ def self.admins_search(string, role) end search_param = "%#{string}%" - joins("LEFT OUTER JOIN users_roles ON users_roles.user_id = users.id LEFT OUTER JOIN roles " \ - "ON roles.id = users_roles.role_id").distinct - .where(search_query, search: search_param, roles_search: role_search_param) + where(search_query, search: search_param, roles_search: role_search_param) end def self.admins_order(column, direction) # Arel.sql to avoid sql injection - order(Arel.sql("#{column} #{direction}")) + order(Arel.sql("users.#{column} #{direction}")) end # Returns a list of rooms ordered by last session (with nil rooms last) @@ -109,6 +109,7 @@ def ordered_rooms # Activates an account and initialize a users main room def activate + set_role :user if role_id.nil? update_attributes(email_verified: true, activated_at: Time.zone.now, activation_digest: nil) end @@ -162,7 +163,7 @@ def greenlight_account? end def admin_of?(user, permission) - has_correct_permission = highest_priority_role.get_permission(permission) && id != user.id + has_correct_permission = role.get_permission(permission) && id != user.id return has_correct_permission unless Rails.configuration.loadbalanced_configuration return id != user.id if has_role? :super_admin @@ -170,70 +171,31 @@ def admin_of?(user, permission) end # role functions - def highest_priority_role - roles.min_by(&:priority) - end - - def add_role(role) - unless has_role?(role) - role_provider = Rails.configuration.loadbalanced_configuration ? provider : "greenlight" + def set_role(role) # rubocop:disable Naming/AccessorMethodName + return if has_role?(role) - new_role = Role.find_by(name: role, provider: role_provider) - - if new_role.nil? - return if Role.duplicate_name(role, role_provider) || role.strip.empty? - - new_role = Role.create_new_role(role, role_provider) - end + new_role = Role.find_by(name: role, provider: role_provider) - roles << new_role + return if new_role.nil? - save! - end - end + create_home_room if main_room.nil? && new_role.get_permission("can_create_rooms") - def remove_role(role) - if has_role?(role) - role_provider = Rails.configuration.loadbalanced_configuration ? provider : "greenlight" + update_attribute(:role, new_role) - roles.delete(Role.find_by(name: role, provider: role_provider)) - save! - end + new_role end # This rule is disabled as the function name must be has_role? - # rubocop:disable Naming/PredicateName - def has_role?(role) - # rubocop:enable Naming/PredicateName - roles.each do |single_role| - return true if single_role.name.eql? role.to_s - end - - false + def has_role?(role_name) # rubocop:disable Naming/PredicateName + role&.name == role_name.to_s end def self.with_role(role) - User.all_users_with_roles.where(roles: { name: role }) + User.includes(:role).where(roles: { name: role }) end def self.without_role(role) - User.where.not(id: with_role(role).pluck(:id)) - end - - def self.with_highest_priority_role(role) - User.all_users_highest_priority_role.where(roles: { name: role }) - end - - 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 INNER JOIN role_permissions ON roles.id = role_permissions.role_id").distinct - end - - def self.all_users_highest_priority_role - User.joins("INNER JOIN (SELECT user_id, min(roles.priority) as role_priority FROM users_roles " \ - "INNER JOIN roles ON users_roles.role_id = roles.id GROUP BY user_id) as a ON " \ - "a.user_id = users.id INNER JOIN roles ON roles.priority = a.role_priority " \ - " INNER JOIN role_permissions ON roles.id = role_permissions.role_id").distinct + User.includes(:role).where.not(roles: { name: role }) end private @@ -246,15 +208,13 @@ def destroy_rooms 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")) - update_attributes(uid: id, main_room: room) + update_attributes(uid: id) # 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 def check_if_email_can_be_blank @@ -266,4 +226,13 @@ def check_if_email_can_be_blank end end end + + def create_home_room + room = Room.create!(owner: self, name: I18n.t("home_room")) + update_attributes(main_room: room) + end + + def role_provider + Rails.configuration.loadbalanced_configuration ? provider : "greenlight" + end end diff --git a/app/views/admins/components/_menu_buttons.html.erb b/app/views/admins/components/_menu_buttons.html.erb index af8f3f12b3..858a1bf76e 100644 --- a/app/views/admins/components/_menu_buttons.html.erb +++ b/app/views/admins/components/_menu_buttons.html.erb @@ -14,7 +14,7 @@ %>
- <% highest_role = current_user.highest_priority_role %> + <% highest_role = current_user.role %> <% highest_role.name %> <% 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 %> diff --git a/app/views/admins/components/_recordings.html.erb b/app/views/admins/components/_recordings.html.erb index 76e8ed1787..8d890fef69 100644 --- a/app/views/admins/components/_recordings.html.erb +++ b/app/views/admins/components/_recordings.html.erb @@ -16,7 +16,7 @@
- +
"> @@ -94,10 +94,10 @@
<% if !@recordings.empty?%> -
+
<%== pagy_bootstrap_nav(@pagy) %>
<% end %>
-
\ No newline at end of file +
diff --git a/app/views/admins/components/_roles.html.erb b/app/views/admins/components/_roles.html.erb index 77a316e1f5..a622bff6d6 100644 --- a/app/views/admins/components/_roles.html.erb +++ b/app/views/admins/components/_roles.html.erb @@ -15,7 +15,7 @@
- <% current_role = current_user.highest_priority_role%> + <% current_role = current_user.role%>
@@ -34,7 +34,7 @@
"> <%= 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.label :name, 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 %> <%= f.hidden_field :colour, id: "role-colour", value: role_colour(@selected_role) %> diff --git a/app/views/admins/components/_rooms.html.erb b/app/views/admins/components/_rooms.html.erb index cfb95a224d..39259229f3 100644 --- a/app/views/admins/components/_rooms.html.erb +++ b/app/views/admins/components/_rooms.html.erb @@ -16,7 +16,7 @@
- +
+ @@ -56,10 +59,10 @@
"> @@ -43,6 +43,9 @@ ↑ <% end %> + <%= t("administrator.rooms.table.participants") %> + <%= t("administrator.rooms.table.status") %>
<% if !@rooms.empty?%> -
+
<%== pagy_bootstrap_nav(@pagy) %>
<% end %>
-
\ No newline at end of file +
diff --git a/app/views/admins/components/_server_recording_row.html.erb b/app/views/admins/components/_server_recording_row.html.erb index bde89c806e..c9c0c31c5d 100644 --- a/app/views/admins/components/_server_recording_row.html.erb +++ b/app/views/admins/components/_server_recording_row.html.erb @@ -15,14 +15,14 @@ -
- +
+ <% if recording[:metadata][:name] %> <%= recording[:metadata][:name] %> <% else %> <%= recording[:name] %> <% end %> - +
diff --git a/app/views/admins/components/_server_room_row.html.erb b/app/views/admins/components/_server_room_row.html.erb index f874452ece..6a37ba55d0 100644 --- a/app/views/admins/components/_server_room_row.html.erb +++ b/app/views/admins/components/_server_room_row.html.erb @@ -15,16 +15,23 @@ data-room-access-code="<%= room.access_code %>"> -
+
<% if room.id == room.owner.room_id %> <% end %> - + <%= room.name %> - +
- <%= [t("administrator.users.table.created"), ": ", room.created_at].join %> + <% running = room_is_running(room.bbb_id) %> + <% if running %> + <%= t("administrator.rooms.table.started", session: friendly_time(room.last_session)) %> + <% elsif room.last_session.present? %> + <%= t("administrator.rooms.table.ended", session: friendly_time(room.last_session)) %> + <% else %> + <%= [t("administrator.users.table.created"), ": ", friendly_time(room.created_at)].join %> + <% end %>
@@ -33,8 +40,10 @@ <%= room.uid %> + + <%= @participants_count[room.bbb_id].presence || "-" %> + - <% running = room_is_running(room.bbb_id) %> <% if running %> <%= t("administrator.rooms.table.running") %> <% else %> diff --git a/app/views/admins/components/_settings.html.erb b/app/views/admins/components/_settings.html.erb index 4dcb0f7357..17c6e8a629 100644 --- a/app/views/admins/components/_settings.html.erb +++ b/app/views/admins/components/_settings.html.erb @@ -28,6 +28,34 @@
+
+
+
+ + +
+ + + + +
+
+
+
+
+
+
+ + +
+ + + + +
+
+
+
diff --git a/app/views/admins/components/_users.html.erb b/app/views/admins/components/_users.html.erb index 8d46812e4a..c58adb3e53 100644 --- a/app/views/admins/components/_users.html.erb +++ b/app/views/admins/components/_users.html.erb @@ -13,21 +13,6 @@ # with BigBlueButton; if not, see . %> -<% -# 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 . -%> - <% if @role.nil? %> <%= render "admins/components/manage_users_tags" %> <% else %> @@ -89,11 +74,10 @@ <%= user.email && user.email != "" ? user.email : user.username%> <%= user.provider %> - <% roles = user.roles().pluck(:name) %> - <%= render "admins/components/admins_role", role: user.highest_priority_role %> + <%= render "admins/components/admins_role", role: user.role %> - <% if !roles.include?("super_admin") %> + <% if !user.has_role?("super_admin") %>