diff --git a/.dockerignore b/.dockerignore index eb2c7816..5da345a5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -25,6 +25,5 @@ vendor/bundle Dockerfile .gitlab-ci.yml .rubocop.yml -.travis.yml spec test \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..74bee889 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ + + + + +## Description + + +## Testing Steps + + +## Screenshots (if appropriate): + diff --git a/.github/workflows/build.push.yml b/.github/workflows/build.push.yml index e281d7ba..3f05b819 100644 --- a/.github/workflows/build.push.yml +++ b/.github/workflows/build.push.yml @@ -22,13 +22,13 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} - name: Compute Short SHA - uses: benjlevesque/short-sha@v1.2 + uses: farhatahmad/short-sha@v1.2 id: short-sha with: length: 7 - name: Get Branch Name - uses: tj-actions/branch-names@v2 + uses: farhatahmad/branch-names@v2 id: branch-name - name: Build and Push latest diff --git a/.github/workflows/build.release.yml b/.github/workflows/build.release.yml index f77fa761..46cecd08 100644 --- a/.github/workflows/build.release.yml +++ b/.github/workflows/build.release.yml @@ -1,31 +1,32 @@ -env: - RUBY_VERSION: 2.7.2 - - -name: Build Release -on: - release: - -jobs: - main: - name: Build Docker Image - runs-on: ubuntu-18.04 - steps: - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Login to Github Container Registry - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Build and Push release - uses: docker/build-push-action@v2 - with: - push: true - tags: | - bigbluebutton/greenlight:latest - bigbluebutton/greenlight:v2 - bigbluebutton/greenlight:${{ github.event.release.tag_name }} - build-args: version_code=${{ github.event.release.tag_name }} +env: + RUBY_VERSION: 2.7.2 + + +name: Build Release +on: + release: + types: [released] + +jobs: + main: + name: Build Docker Image + runs-on: ubuntu-18.04 + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Github Container Registry + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and Push release + uses: docker/build-push-action@v2 + with: + push: true + tags: | + bigbluebutton/greenlight:latest + bigbluebutton/greenlight:v2 + bigbluebutton/greenlight:${{ github.event.release.tag_name }} + build-args: version_code=${{ github.event.release.tag_name }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 435439aa..933eb725 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,65 +1,65 @@ -env: - RUBY_VERSION: 2.7.2 - DB_ADAPTER: postgresql - DB_HOST: localhost - DB_NAME: postgres - DB_USERNAME: postgres - DB_PASSWORD: postgres - DB_PORT: 5432 - -name: CI -on: - push: - branches: "master" - pull_request: - branches: "*" - -jobs: - test: - name: Rubocop + RSpec - runs-on: ubuntu-18.04 - - services: - postgres: - image: postgres - env: - POSTGRES_DB: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - ports: - - 5432:5432 - # Health checks to wait until postgres is ready - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install Ruby ${{ env.RUBY_VERSION }} - uses: actions/setup-ruby@v1 - with: - ruby-version: ${{ env.RUBY_VERSION }} - - - name: Bundle cache - uses: actions/cache@v2 - with: - path: vendor/bundle - key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} - restore-keys: | - ${{ runner.os }}-gems- - - name: Bundle install - run: | - bundle config path vendor/bundle - bundle install --jobs 4 --retry 3 - - name: Setup database - run: | - bundler exec rails db:create RAILS_ENV=test - bundler exec rails db:migrate RAILS_ENV=test - - name: Run Rubocop - run: bundle exec rubocop --parallel --fail-level F - - - name: Run RSpec - run: bundle exec rspec \ No newline at end of file +env: + RUBY_VERSION: 2.7.2 + DB_ADAPTER: postgresql + DB_HOST: localhost + DB_NAME: postgres + DB_USERNAME: postgres + DB_PASSWORD: postgres + DB_PORT: 5432 + +name: CI +on: + pull_request: + branches: "*" + +jobs: + test: + name: Rubocop + RSpec + runs-on: ubuntu-18.04 + + services: + postgres: + image: postgres:13.2-alpine + env: + POSTGRES_DB: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_USER: postgres + ports: + - 5432:5432 + # Health checks to wait until postgres is ready + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Ruby Setup + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + + - name: Bundle cache + uses: actions/cache@v2 + with: + path: vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Bundle install + run: | + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - name: Setup database + run: | + bundler exec rails db:create RAILS_ENV=test + bundler exec rails db:migrate RAILS_ENV=test + - name: Run Rubocop + run: bundle exec rubocop --parallel --fail-level F + + - name: Run RSpec + run: bundle exec rspec diff --git a/.rubocop.yml b/.rubocop.yml index 0e7a2d4f..9d14d92c 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,11 +3,9 @@ AllCops: - 'db/schema.rb' - 'vendor/**/*' DisabledByDefault: false - TargetRubyVersion: 2.5 + TargetRubyVersion: 2.7 -# Gems within groups in the Gemfile should be alphabetically sorted. -Bundler/OrderedGems: - Enabled: false + NewCops: enable Style/BlockDelimiters: Enabled: false @@ -138,7 +136,7 @@ Metrics/AbcSize: # A complexity metric that is strongly correlated to the number # of test cases needed to validate a method. Metrics/CyclomaticComplexity: - Max: 17 + Max: 20 # Checks for method parameter names that contain capital letters, end in numbers, or do not meet a minimal length. Naming/MethodParameterName: @@ -176,4 +174,18 @@ Style/HashTransformValues: Style/SlicingWithRange: Enabled: true - \ No newline at end of file + +Style/OptionalBooleanParameter: + Enabled: false + +Lint/DuplicateBranch: + Enabled: false + +Lint/ConstantDefinitionInBlock: + Enabled: false + +Lint/EmptyBlock: + Enabled: false + +Style/HashLikeCase: + Enabled: false diff --git a/.ruby-version b/.ruby-version index 73462a5a..37c2961c 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.5.1 +2.7.2 diff --git a/Dockerfile b/Dockerfile index d2fbe32e..ad0a5e2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.5.1-alpine AS base +FROM ruby:2.7.2-alpine AS base # Set a variable for the install location. ARG RAILS_ROOT=/usr/src/app @@ -24,9 +24,9 @@ COPY Gemfile Gemfile.lock $RAILS_ROOT/ RUN bundle config --global frozen 1 \ && bundle install --deployment --without development:test:assets -j4 --path=vendor/bundle \ - && rm -rf vendor/bundle/ruby/2.5.0/cache/*.gem \ - && find vendor/bundle/ruby/2.5.0/gems/ -name "*.c" -delete \ - && find vendor/bundle/ruby/2.5.0/gems/ -name "*.o" -delete + && rm -rf vendor/bundle/ruby/2.7.0/cache/*.gem \ + && find vendor/bundle/ruby/2.7.0/gems/ -name "*.c" -delete \ + && find vendor/bundle/ruby/2.7.0/gems/ -name "*.o" -delete # Adding project files. COPY . . @@ -36,7 +36,7 @@ RUN rm -rf tmp/cache spec ############### Build step done ############### -FROM ruby:2.5.1-alpine +FROM ruby:2.7.2-alpine # Set a variable for the install location. ARG RAILS_ROOT=/usr/src/app diff --git a/Gemfile b/Gemfile index 1fe7ac8c..5cf25d29 100644 --- a/Gemfile +++ b/Gemfile @@ -8,138 +8,72 @@ git_source(:github) do |repo_name| end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.2.4.4' - -# Use Puma as the app server -gem 'puma', '~> 3.12' - -# Use SCSS for stylesheets -gem 'sassc-rails' - -# Use Uglifier as compressor for JavaScript assets -gem 'uglifier', '>= 1.3.0' - -# Use CoffeeScript for .coffee assets and views -gem 'coffee-rails', '~> 4.2' - -# See https://github.com/rails/execjs#readme for more supported runtimes -# gem 'mini_racer', platforms: :ruby - -# Use jquery as the JavaScript library -gem 'jquery-rails', '~> 4.4' -gem 'jquery-ui-rails' - -# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks -gem 'turbolinks', '~> 5' - -# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder', '~> 2.5' - -# Use Redis adapter to run Action Cable in production -# gem 'redis', '~> 3.0' - -# Use ActiveModel has_secure_password +gem 'aws-sdk-s3', '~> 1.88.1' 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' -gem 'omniauth-google-oauth2' -gem 'omniauth_openid_connect' -gem 'omniauth-bn-launcher', '~> 0.1.3' -gem 'net-ldap' -gem 'bn-ldap-authentication', '~> 0.1.4' -gem 'omniauth-bn-office365', '~> 0.1.1' - -# BigBlueButton API wrapper. gem 'bigbluebutton-api-ruby', git: 'https://github.com/mconf/bigbluebutton-api-ruby.git', branch: 'master' - -# Front-end. +gem 'bn-ldap-authentication', '~> 0.1.4' +gem 'bootsnap', '~> 1.7.2', require: false gem 'bootstrap', '~> 4.3.1' -gem 'tabler-rubygem', git: 'https://github.com/blindsidenetworks/tabler-rubygem.git', tag: '0.1.4.1' -gem 'pagy' +gem 'cancancan', '~> 2.3.0' +gem 'coveralls', '~> 0.8.23', require: false gem 'font-awesome-sass', '~> 5.9.0' - -# For detecting the users preferred language. -gem 'http_accept_language' - -# Use Capistrano for deployment -# gem 'capistrano-rails', group: :development - -# Markdown parsing. -gem 'redcarpet' - -# For limiting access based on user roles -gem 'cancancan', '~> 2.0' - -# Active Storage gems -gem 'aws-sdk-s3', '~> 1.75' -gem 'google-cloud-storage', '~> 1.26' - -gem 'pluck_to_hash', '~> 1.0.2' - +gem 'google-cloud-storage', '~> 1.30.0' +gem 'http_accept_language', '~> 2.1.1' +gem 'i18n-language-mapping', '~> 0.1.1' +gem 'jbuilder', '~> 2.11.2' +gem 'jquery-rails', '~> 4.4.0' +gem 'jquery-ui-rails', '~> 6.0.1' gem 'local_time', '~> 2.1.0' +gem 'net-ldap', '~> 0.17.0' +gem 'omniauth', '~> 1.9.1' +gem 'omniauth-bn-launcher', '~> 0.1.3' +gem 'omniauth-bn-office365', '~> 0.1.1' +gem 'omniauth-google-oauth2', '~> 0.7.0' +gem 'omniauth_openid_connect', '~> 0.3.5' +gem 'omniauth-twitter', '~> 1.4.0' +gem 'pagy', '~> 3.11.0' +gem 'pluck_to_hash', '~> 1.0.2' +gem 'puma', '~> 3.12.6' +gem 'rails', '~> 5.2.6' +gem 'random_password', '~> 0.1.1' +gem "recaptcha", '~> 5.7.0' +gem 'redcarpet', '~> 3.5.1' +gem 'remote_syslog_logger', '~> 1.0.4' +gem 'rubocop', '~> 1.10.0' +gem 'sassc-rails', '~> 2.1.2' +gem 'sprockets', '~> 3.7.2' +gem 'sqlite3', '~> 1.3.6' +gem 'tabler-rubygem', git: 'https://github.com/blindsidenetworks/tabler-rubygem.git', tag: '0.1.4.1' +gem 'turbolinks', '~> 5.2.1' +gem 'tzinfo-data', '~> 1.2021.1' +gem 'uglifier', '~> 4.2.0' group :production do - # Use a postgres database in production. + gem 'hiredis', '~> 0.6.3' + gem "lograge", '~> 0.11.2' gem 'pg', '~> 0.18' - gem 'sequel' - - # For a better logging library in production - gem "lograge" - - # Use for the cache store in production - gem 'redis' - gem 'hiredis' + gem 'redis', '~> 4.2.5' + gem 'sequel', '~> 5.41.0' end -# Ruby linting. -gem 'rubocop' - group :development, :test do - # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug', platform: :mri - # Environment configuration. - gem 'dotenv-rails' - # Use a sqlite database in test and development. - gem 'sqlite3', '~> 1.3.6' + gem 'byebug', '~> 11.1', platform: :mri + gem 'dotenv-rails', '~> 2.7' end group :test do - # Include Rspec and other testing utilities. + gem 'action-cable-testing', '~> 0.6' + gem "factory_bot_rails", '~> 6.1' + gem 'faker', '~> 2.16' + gem 'rails-controller-testing', '~> 1.0' gem 'rspec-rails', '~> 3.7' - gem 'action-cable-testing' - gem 'rails-controller-testing' gem 'shoulda-matchers', '~> 3.1' - gem 'faker' - gem "factory_bot_rails" - gem 'webmock' + gem 'webmock', '~> 3.11' end group :development do - # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. - gem 'web-console', '>= 3.3.0' - gem 'listen', '~> 3.0.5' - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' - gem 'spring-watcher-listen', '~> 2.0.0' + gem 'listen', '~> 3.0' + gem 'spring', '~> 2.1' + gem 'spring-watcher-listen', '~> 2.0' + gem 'web-console', '~> 3.7' end - -gem 'remote_syslog_logger' - -# Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data' - -gem 'coveralls', require: false - -gem 'random_password' - -# Adds helpers for the Google reCAPTCHA API -gem "recaptcha" - -gem 'i18n-language-mapping', '~> 0.1.1' diff --git a/Gemfile.lock b/Gemfile.lock index d0c5d412..c7c4eee0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,43 +25,43 @@ GEM specs: action-cable-testing (0.6.1) actioncable (>= 5.0) - actioncable (5.2.4.4) - actionpack (= 5.2.4.4) + actioncable (5.2.6) + actionpack (= 5.2.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.4) - actionpack (= 5.2.4.4) - actionview (= 5.2.4.4) - activejob (= 5.2.4.4) + actionmailer (5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.4) - actionview (= 5.2.4.4) - activesupport (= 5.2.4.4) + actionpack (5.2.6) + actionview (= 5.2.6) + activesupport (= 5.2.6) 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.4.4) - activesupport (= 5.2.4.4) + actionview (5.2.6) + activesupport (= 5.2.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.4.4) - activesupport (= 5.2.4.4) + activejob (5.2.6) + activesupport (= 5.2.6) globalid (>= 0.3.6) - activemodel (5.2.4.4) - activesupport (= 5.2.4.4) - activerecord (5.2.4.4) - activemodel (= 5.2.4.4) - activesupport (= 5.2.4.4) + activemodel (5.2.6) + activesupport (= 5.2.6) + activerecord (5.2.6) + activemodel (= 5.2.6) + activesupport (= 5.2.6) arel (>= 9.0) - activestorage (5.2.4.4) - actionpack (= 5.2.4.4) - activerecord (= 5.2.4.4) - marcel (~> 0.3.1) - activesupport (5.2.4.4) + activestorage (5.2.6) + actionpack (= 5.2.6) + activerecord (= 5.2.6) + marcel (~> 1.0.0) + activesupport (5.2.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -70,32 +70,32 @@ GEM public_suffix (>= 2.0.2, < 5.0) aes_key_wrap (1.1.0) arel (9.0.0) - ast (2.4.0) + ast (2.4.2) attr_required (1.0.1) - autoprefixer-rails (9.7.6) + autoprefixer-rails (10.2.4.0) execjs - aws-eventstream (1.1.0) - aws-partitions (1.343.0) - aws-sdk-core (3.104.1) + aws-eventstream (1.1.1) + aws-partitions (1.435.0) + aws-sdk-core (3.113.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.36.0) - aws-sdk-core (~> 3, >= 3.99.0) + aws-sdk-kms (1.43.0) + aws-sdk-core (~> 3, >= 3.112.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.75.0) - aws-sdk-core (~> 3, >= 3.104.1) + aws-sdk-s3 (1.88.2) + aws-sdk-core (~> 3, >= 3.112.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.1) + aws-sigv4 (1.2.3) aws-eventstream (~> 1, >= 1.0.2) - bcrypt (3.1.13) + bcrypt (3.1.16) bindata (2.4.8) bindex (0.8.1) bn-ldap-authentication (0.1.4) net-ldap (~> 0) - bootsnap (1.4.6) + bootsnap (1.7.3) msgpack (~> 1.0) bootstrap (4.3.1) autoprefixer-rails (>= 9.1.0) @@ -105,71 +105,74 @@ GEM byebug (11.1.3) cancancan (2.3.0) childprocess (4.0.0) - coffee-rails (4.2.2) - coffee-script (>= 2.2.0) - railties (>= 4.0.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) - concurrent-ruby (1.1.7) + concurrent-ruby (1.1.8) coveralls (0.8.23) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (>= 0.19.4, < 2.0) tins (~> 1.6) - crack (0.4.3) - safe_yaml (~> 1.0.0) + crack (0.4.5) + rexml crass (1.0.6) declarative (0.0.20) declarative-option (0.1.0) - diff-lcs (1.3) - digest-crc (0.6.1) - rake (~> 13.0) - docile (1.3.2) - dotenv (2.7.5) - dotenv-rails (2.7.5) - dotenv (= 2.7.5) - railties (>= 3.2, < 6.1) - erubi (1.9.0) + diff-lcs (1.4.4) + digest-crc (0.6.3) + rake (>= 12.0.0, < 14.0.0) + docile (1.3.5) + dotenv (2.7.6) + dotenv-rails (2.7.6) + dotenv (= 2.7.6) + railties (>= 3.2) + erubi (1.10.0) execjs (2.7.0) - factory_bot (5.2.0) - activesupport (>= 4.2.0) - factory_bot_rails (5.2.0) - factory_bot (~> 5.2.0) - railties (>= 4.2.0) - faker (2.11.0) + factory_bot (6.1.0) + activesupport (>= 5.0.0) + factory_bot_rails (6.1.0) + factory_bot (~> 6.1.0) + railties (>= 5.0.0) + faker (2.17.0) i18n (>= 1.6, < 2) - faraday (1.0.1) + faraday (1.3.0) + faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) - ffi (1.12.2) + ruby2_keywords + faraday-net_http (1.0.1) + ffi (1.15.0) font-awesome-sass (5.9.0) sassc (>= 1.11) globalid (0.4.2) activesupport (>= 4.2.0) - google-api-client (0.42.1) + google-apis-core (0.3.0) addressable (~> 2.5, >= 2.5.1) - googleauth (~> 0.9) + googleauth (~> 0.14) httpclient (>= 2.8.1, < 3.0) mini_mime (~> 1.0) representable (~> 3.0) retriable (>= 2.0, < 4.0) - signet (~> 0.12) - google-cloud-core (1.5.0) + rexml + signet (~> 0.14) + webrick + google-apis-iamcredentials_v1 (0.2.0) + google-apis-core (~> 0.1) + google-apis-storage_v1 (0.3.0) + google-apis-core (~> 0.1) + google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) - google-cloud-env (1.3.3) + google-cloud-env (1.5.0) faraday (>= 0.17.3, < 2.0) - google-cloud-errors (1.0.1) - google-cloud-storage (1.26.2) + google-cloud-errors (1.1.0) + google-cloud-storage (1.30.0) addressable (~> 2.5) digest-crc (~> 0.4) - google-api-client (~> 0.33) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.1) google-cloud-core (~> 1.2) googleauth (~> 0.9) mini_mime (~> 1.0) - googleauth (0.13.0) + googleauth (0.16.0) faraday (>= 0.17.3, < 2.0) jwt (>= 1.4, < 3.0) memoist (~> 0.16) @@ -181,10 +184,10 @@ GEM hiredis (0.6.3) http_accept_language (2.1.1) httpclient (2.8.3) - i18n (1.8.5) + i18n (1.8.10) concurrent-ruby (~> 1.0) i18n-language-mapping (0.1.2) - jbuilder (2.10.0) + jbuilder (2.11.2) activesupport (>= 5.0.0) jmespath (1.4.0) jquery-rails (4.4.0) @@ -193,45 +196,43 @@ GEM thor (>= 0.14, < 2.0) jquery-ui-rails (6.0.1) railties (>= 3.2.16) - json (2.3.0) + json (2.5.1) json-jwt (1.13.0) activesupport (>= 4.2) aes_key_wrap bindata - jwt (2.2.1) - listen (3.0.8) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) + jwt (2.2.2) + listen (3.5.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) local_time (2.1.0) lograge (0.11.2) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.7.0) + loofah (2.9.1) 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) + marcel (1.0.1) memoist (0.16.2) method_source (1.0.0) - mimemagic (0.3.5) - mini_mime (1.0.2) - mini_portile2 (2.5.0) - minitest (5.14.2) - msgpack (1.3.3) - multi_json (1.14.1) + mini_mime (1.1.0) + mini_portile2 (2.5.1) + minitest (5.14.4) + msgpack (1.4.2) + multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.1.1) - net-ldap (0.16.2) - nio4r (2.5.4) - nokogiri (1.11.1) + net-ldap (0.17.0) + nio4r (2.5.7) + nokogiri (1.11.3) mini_portile2 (~> 2.5.0) racc (~> 1.4) - oauth (0.5.4) - oauth2 (1.4.4) + oauth (0.5.5) + oauth2 (1.4.7) faraday (>= 0.8, < 2.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) @@ -250,9 +251,9 @@ GEM jwt (>= 2.0) omniauth (>= 1.1.1) omniauth-oauth2 (>= 1.5) - omniauth-oauth (1.1.0) + omniauth-oauth (1.2.0) oauth - omniauth (~> 1.0) + omniauth (>= 1.0, < 3) omniauth-oauth2 (1.5.0) oauth2 (~> 1.1) omniauth (~> 1.2) @@ -273,17 +274,17 @@ GEM validate_email validate_url webfinger (>= 1.0.1) - os (1.1.0) - pagy (3.8.1) - parallel (1.19.1) - parser (2.7.1.3) - ast (~> 2.4.0) + os (1.1.1) + pagy (3.11.0) + parallel (1.20.1) + parser (3.0.0.0) + ast (~> 2.4.1) pg (0.21.0) pluck_to_hash (1.0.2) activerecord (>= 4.0.2) activesupport (>= 4.0.2) popper_js (1.16.0) - public_suffix (4.0.5) + public_suffix (4.0.6) puma (3.12.6) racc (1.5.2) rack (2.2.3) @@ -295,44 +296,45 @@ GEM rack (>= 2.1.0) rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.2.4.4) - actioncable (= 5.2.4.4) - actionmailer (= 5.2.4.4) - actionpack (= 5.2.4.4) - actionview (= 5.2.4.4) - activejob (= 5.2.4.4) - activemodel (= 5.2.4.4) - activerecord (= 5.2.4.4) - activestorage (= 5.2.4.4) - activesupport (= 5.2.4.4) + rails (5.2.6) + actioncable (= 5.2.6) + actionmailer (= 5.2.6) + actionpack (= 5.2.6) + actionview (= 5.2.6) + activejob (= 5.2.6) + activemodel (= 5.2.6) + activerecord (= 5.2.6) + activestorage (= 5.2.6) + activesupport (= 5.2.6) bundler (>= 1.3.0) - railties (= 5.2.4.4) + railties (= 5.2.6) sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.4) - actionpack (>= 5.0.1.x) - actionview (>= 5.0.1.x) - activesupport (>= 5.0.1.x) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.3.0) loofah (~> 2.3) - railties (5.2.4.4) - actionpack (= 5.2.4.4) - activesupport (= 5.2.4.4) + railties (5.2.6) + actionpack (= 5.2.6) + activesupport (= 5.2.6) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) - rake (13.0.1) + rake (13.0.3) random_password (0.1.1) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) - recaptcha (5.5.0) + recaptcha (5.7.0) json redcarpet (3.5.1) - redis (4.1.4) + redis (4.2.5) + regexp_parser (2.1.1) remote_syslog_logger (1.0.4) syslog_protocol representable (3.0.4) @@ -342,10 +344,10 @@ GEM request_store (1.5.0) rack (>= 1.4) retriable (3.1.2) - rexml (3.2.4) - rspec-core (3.9.2) + rexml (3.2.5) + rspec-core (3.9.3) rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rspec-expectations (3.9.4) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) rspec-mocks (3.9.1) @@ -359,21 +361,22 @@ GEM rspec-expectations (~> 3.9.0) rspec-mocks (~> 3.9.0) rspec-support (~> 3.9.0) - rspec-support (3.9.3) - rubocop (0.84.0) + rspec-support (3.9.4) + rubocop (1.10.0) parallel (~> 1.10) - parser (>= 2.7.0.1) + parser (>= 3.0.0.0) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 0.0.3) + rubocop-ast (>= 1.2.0, < 2.0) ruby-progressbar (~> 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) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.4.1) + parser (>= 2.7.1.5) + ruby-progressbar (1.11.0) + ruby2_keywords (0.0.4) rubyzip (2.3.0) - safe_yaml (1.0.5) - sassc (2.3.0) + sassc (2.4.0) ffi (~> 1.9) sassc-rails (2.1.2) railties (>= 4.0.0) @@ -381,10 +384,10 @@ GEM sprockets (> 3.0) sprockets-rails tilt - sequel (5.32.0) + sequel (5.41.0) shoulda-matchers (3.1.3) activesupport (>= 4.0.0) - signet (0.14.0) + signet (0.15.0) addressable (~> 2.3) faraday (>= 0.17.3, < 2.0) jwt (>= 1.5, < 3.0) @@ -394,7 +397,7 @@ GEM json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - spring (2.1.0) + spring (2.1.1) spring-watcher-listen (2.0.1) listen (>= 2.7, < 4.0) spring (>= 1.2, < 3.0) @@ -414,22 +417,22 @@ GEM syslog_protocol (0.9.2) term-ansicolor (1.7.1) tins (~> 1.0) - thor (1.0.1) + thor (1.1.0) thread_safe (0.3.6) tilt (2.0.10) - tins (1.25.0) + tins (1.28.0) sync turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) - tzinfo (1.2.7) + tzinfo (1.2.9) thread_safe (~> 0.1) - tzinfo-data (1.2020.1) + tzinfo-data (1.2021.1) tzinfo (>= 1.0.0) uber (0.1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) - unicode-display_width (1.7.0) + unicode-display_width (2.0.0) validate_email (0.1.6) activemodel (>= 3.0) mail (>= 2.2.5) @@ -444,74 +447,74 @@ GEM webfinger (1.1.0) activesupport httpclient (>= 2.4) - webmock (3.8.3) + webmock (3.12.1) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) + webrick (1.7.0) websocket-driver (0.7.3) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - xml-simple (1.1.5) + xml-simple (1.1.8) PLATFORMS ruby DEPENDENCIES - action-cable-testing - aws-sdk-s3 (~> 1.75) + action-cable-testing (~> 0.6) + aws-sdk-s3 (~> 1.88.1) bcrypt (~> 3.1.7) bigbluebutton-api-ruby! bn-ldap-authentication (~> 0.1.4) - bootsnap (>= 1.1.0) + bootsnap (~> 1.7.2) bootstrap (~> 4.3.1) - byebug - cancancan (~> 2.0) - coffee-rails (~> 4.2) - coveralls - dotenv-rails - factory_bot_rails - faker + byebug (~> 11.1) + cancancan (~> 2.3.0) + coveralls (~> 0.8.23) + dotenv-rails (~> 2.7) + factory_bot_rails (~> 6.1) + faker (~> 2.16) font-awesome-sass (~> 5.9.0) - google-cloud-storage (~> 1.26) - hiredis - http_accept_language + google-cloud-storage (~> 1.30.0) + hiredis (~> 0.6.3) + http_accept_language (~> 2.1.1) i18n-language-mapping (~> 0.1.1) - jbuilder (~> 2.5) - jquery-rails (~> 4.4) - jquery-ui-rails - listen (~> 3.0.5) + jbuilder (~> 2.11.2) + jquery-rails (~> 4.4.0) + jquery-ui-rails (~> 6.0.1) + listen (~> 3.0) local_time (~> 2.1.0) - lograge - net-ldap - omniauth + lograge (~> 0.11.2) + net-ldap (~> 0.17.0) + omniauth (~> 1.9.1) omniauth-bn-launcher (~> 0.1.3) omniauth-bn-office365 (~> 0.1.1) - omniauth-google-oauth2 - omniauth-twitter - omniauth_openid_connect - pagy + omniauth-google-oauth2 (~> 0.7.0) + omniauth-twitter (~> 1.4.0) + omniauth_openid_connect (~> 0.3.5) + pagy (~> 3.11.0) pg (~> 0.18) pluck_to_hash (~> 1.0.2) - puma (~> 3.12) - rails (~> 5.2.4.4) - rails-controller-testing - random_password - recaptcha - redcarpet - redis - remote_syslog_logger + puma (~> 3.12.6) + rails (~> 5.2.6) + rails-controller-testing (~> 1.0) + random_password (~> 0.1.1) + recaptcha (~> 5.7.0) + redcarpet (~> 3.5.1) + redis (~> 4.2.5) + remote_syslog_logger (~> 1.0.4) rspec-rails (~> 3.7) - rubocop - sassc-rails - sequel + rubocop (~> 1.10.0) + sassc-rails (~> 2.1.2) + sequel (~> 5.41.0) shoulda-matchers (~> 3.1) - spring - spring-watcher-listen (~> 2.0.0) - sprockets (< 4.0.0) + spring (~> 2.1) + spring-watcher-listen (~> 2.0) + sprockets (~> 3.7.2) sqlite3 (~> 1.3.6) tabler-rubygem! - turbolinks (~> 5) - tzinfo-data - uglifier (>= 1.3.0) - web-console (>= 3.3.0) - webmock + turbolinks (~> 5.2.1) + tzinfo-data (~> 1.2021.1) + uglifier (~> 4.2.0) + web-console (~> 3.7) + webmock (~> 3.11) diff --git a/README.md b/README.md index 454102cc..f94a8966 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Greenlight -   @@ -33,4 +32,6 @@ Greenlight is built using Ruby on Rails. Many developers already know Rails well We invite you to build upon Greenlight and help make it better. See [Contributing to BigBlueButton](http://docs.bigbluebutton.org/support/faq.html#contributing-to-bigbluebutton). -We invite your feedback, questions, and suggests about Greenlight too. Please post them to the [developer mailing list](https://groups.google.com/forum/#!forum/bigbluebutton-dev). +We invite your feedback, questions, and suggests about Greenlight too. Please post them to the [Greenlight mailing list](https://groups.google.com/forum/#!forum/bigbluebutton-greenlight). + +To help with organization and consistency, we have implemented a Pull Request template that must be used for all Pull Requests. This template helps ensure that the project maintainers can review all PRs in a timely manner. When creating a Pull Request, please provide as much information as possible. \ No newline at end of file diff --git a/app/assets/javascripts/room.js b/app/assets/javascripts/room.js index d5861d8f..d953f613 100644 --- a/app/assets/javascripts/room.js +++ b/app/assets/javascripts/room.js @@ -184,17 +184,19 @@ function copyInvite() { } } -function copyAccess() { - $('#copy-code').attr("type", "text") - $('#copy-code').select() +function copyAccess(target) { + input = target ? $("#copy-" + target + "-code") : $("#copy-code") + input.attr("type", "text") + input.select() if (document.execCommand("copy")) { - $('#copy-code').attr("type", "hidden") - copy = $("#copy-access") + input.attr("type", "hidden") + copy = target ? $("#copy-" + target + "-access") : $("#copy-access") copy.addClass('btn-success'); copy.html("" + getLocalizedString("copied")) setTimeout(function(){ copy.removeClass('btn-success'); - copy.html("" + getLocalizedString("room.copy_access")) + originalString = target ? getLocalizedString("room.copy_" + target + "_access") : getLocalizedString("room.copy_access") + copy.html("" + originalString) }, 1000) } } @@ -202,7 +204,9 @@ function copyAccess() { function showCreateRoom(target) { $("#create-room-name").val("") $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) + $("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code_placeholder")) $("#room_access_code").val(null) + $("#room_moderator_access_code").val(null) $("#createRoomModal form").attr("action", $("body").data('relative-root')) $("#room_mute_on_join").prop("checked", $("#room_mute_on_join").data("default")) @@ -254,6 +258,16 @@ function showUpdateRoom(target) { $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder")) $("#room_access_code").val(null) } + + var moderatorAccessCode = modal.closest(".room-block").data("room-moderator-access-code") + + if(moderatorAccessCode){ + $("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code") + ": " + moderatorAccessCode) + $("#room_moderator_access_code").val(moderatorAccessCode) + } else { + $("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code_placeholder")) + $("#room_moderator_access_code").val(null) + } } function showDeleteRoom(target) { @@ -291,6 +305,24 @@ function ResetAccessCode(){ $("#room_access_code").val(null) } +function generateModeratorAccessCode(){ + const accessCodeLength = 6 + var validCharacters = "abcdefghijklmopqrstuvwxyz" + var accessCode = "" + + for( var i = 0; i < accessCodeLength; i++){ + accessCode += validCharacters.charAt(Math.floor(Math.random() * validCharacters.length)); + } + + $("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code") + ": " + accessCode) + $("#room_moderator_access_code").val(accessCode) +} + +function ResetModeratorAccessCode(){ + $("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code_placeholder")) + $("#room_moderator_access_code").val(null) +} + function saveAccessChanges() { let listItemsToAdd = $("#user-list li:not(.remove-shared)").toArray().map(user => $(user).data("uid")) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 13b0c128..fb85489f 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -187,3 +187,7 @@ table { .btn i { transition: all .15s; } + +.nav-icon i { + width: 35px; +} diff --git a/app/assets/stylesheets/rooms.scss b/app/assets/stylesheets/rooms.scss index 26709952..573ec5c4 100644 --- a/app/assets/stylesheets/rooms.scss +++ b/app/assets/stylesheets/rooms.scss @@ -32,8 +32,8 @@ font-size: 20px !important; } -.join-input { - height: 48px; +.moderator-code-label { + margin-top: 150px !important; } .home-indicator { diff --git a/app/controllers/account_activations_controller.rb b/app/controllers/account_activations_controller.rb index 0de5e776..7fa4f1dc 100644 --- a/app/controllers/account_activations_controller.rb +++ b/app/controllers/account_activations_controller.rb @@ -41,7 +41,7 @@ class AccountActivationsController < ApplicationController flash: { success: I18n.t("registration.approval.signup") } if @user.has_role?(:pending) # Redirect user to sign in path with success flash - redirect_to signin_path, flash: { success: I18n.t("verify.activated") + " " + I18n.t("verify.signin") } + redirect_to signin_path, flash: { success: "#{I18n.t('verify.activated')} #{I18n.t('verify.signin')}" } else redirect_to root_path, flash: { alert: I18n.t("verify.invalid") } end diff --git a/app/controllers/admins_controller.rb b/app/controllers/admins_controller.rb index f8412ccc..ce752999 100644 --- a/app/controllers/admins_controller.rb +++ b/app/controllers/admins_controller.rb @@ -145,10 +145,11 @@ class AdminsController < ApplicationController emails.each do |email| invitation = create_or_update_invite(email) - send_invitation_email(current_user.name, email, invitation.invite_token) + send_invitation_email(current_user.name, email, invitation) end - redirect_back fallback_location: admins_path + redirect_back fallback_location: admins_path, + flash: { success: I18n.t("administrator.flash.invite", email: emails.join(", ")) } end # GET /admins/reset @@ -228,7 +229,7 @@ class AdminsController < ApplicationController flash_message = I18n.t("administrator.flash.settings") if params[:value] == "Default Recording Visibility" - flash_message += ". " + I18n.t("administrator.site_settings.recording_visibility.warning") + flash_message += ". #{I18n.t('administrator.site_settings.recording_visibility.warning')}" end redirect_to admin_site_settings_path(tab: tab), flash: { success: flash_message } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f3cb5248..cfdd66c8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -29,13 +29,11 @@ class ApplicationController < ActionController::Base def current_user @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) && - @current_user.provider != @user_domain + if Rails.configuration.loadbalanced_configuration && (@current_user && !@current_user.has_role?(:super_admin) && + @current_user.provider != @user_domain) @current_user = nil session.clear end - end @current_user end @@ -86,8 +84,8 @@ class ApplicationController < ActionController::Base end maintenance_string = @settings.get_value("Maintenance Banner").presence || Rails.configuration.maintenance_window - if maintenance_string.present? - flash.now[:maintenance] = maintenance_string unless cookies[:maintenance_window] == maintenance_string + if maintenance_string.present? && cookies[:maintenance_window] != maintenance_string + flash.now[:maintenance] = maintenance_string end end @@ -188,6 +186,12 @@ class ApplicationController < ActionController::Base end helper_method :recording_consent_required? + # Indicates whether users are allowed to add moderator access codes to rooms + def moderator_code_allowed? + @settings.get_value("Room Configuration Moderator Access Codes") == "optional" + end + helper_method :moderator_code_allowed? + # Returns a list of allowed file types def allowed_file_types Rails.configuration.allowed_file_types @@ -268,17 +272,18 @@ class ApplicationController < ActionController::Base rescue => e logger.error "Error in retrieve provider info: #{e}" @hide_signin = true - if e.message.eql? "No user with that id exists" + case e.message + when "No user with that id exists" set_default_settings render "errors/greenlight_error", locals: { message: I18n.t("errors.not_found.user_not_found.message"), help: I18n.t("errors.not_found.user_not_found.help") } - elsif e.message.eql? "Provider not included." + when "Provider not included." set_default_settings render "errors/greenlight_error", locals: { message: I18n.t("errors.not_found.user_missing.message"), help: I18n.t("errors.not_found.user_missing.help") } - elsif e.message.eql? "That user has no configured provider." + when "That user has no configured provider." if Setting.exists?(provider: @user_domain) # Keep the branding @settings = Setting.find_by(provider: @user_domain) diff --git a/app/controllers/concerns/authenticator.rb b/app/controllers/concerns/authenticator.rb index 577bf571..10b1eee6 100644 --- a/app/controllers/concerns/authenticator.rb +++ b/app/controllers/concerns/authenticator.rb @@ -113,7 +113,7 @@ module Authenticator old_user.rooms.each do |room| room.owner = user - room.name = "Old " + room.name if room.id == old_user.main_room.id + room.name = "Old #{room.name}" if room.id == old_user.main_room.id room.save! end diff --git a/app/controllers/concerns/emailer.rb b/app/controllers/concerns/emailer.rb index aeb48b1d..bd87287c 100644 --- a/app/controllers/concerns/emailer.rb +++ b/app/controllers/concerns/emailer.rb @@ -70,16 +70,14 @@ module Emailer end # Sends inivitation to join - def send_invitation_email(name, email, token) + def send_invitation_email(name, email, invite) begin return unless Rails.configuration.enable_email_verification - UserMailer.invite_email(name, email, invitation_link(token), @settings).deliver_now + UserMailer.invite_email(name, email, invite.updated_at, invitation_link(invite.invite_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 diff --git a/app/controllers/concerns/joiner.rb b/app/controllers/concerns/joiner.rb index 96958c05..6c6b016e 100644 --- a/app/controllers/concerns/joiner.rb +++ b/app/controllers/concerns/joiner.rb @@ -50,10 +50,11 @@ module Joiner def join_room(opts) @room_settings = JSON.parse(@room[:room_settings]) - if room_running?(@room.bbb_id) || @room.owned_by?(current_user) || room_setting_with_config("anyoneCanStart") + moderator_privileges = @room.owned_by?(current_user) || valid_moderator_access_code(session[:moderator_access_code]) + if room_running?(@room.bbb_id) || room_setting_with_config("anyoneCanStart") || moderator_privileges # Determine if the user needs to join as a moderator. - opts[:user_is_moderator] = @room.owned_by?(current_user) || room_setting_with_config("joinModerator") || @shared_room + opts[:user_is_moderator] = room_setting_with_config("joinModerator") || @shared_room || moderator_privileges opts[:record] = record_meeting opts[:require_moderator_approval] = room_setting_with_config("requireModeratorApproval") opts[:mute_on_start] = room_setting_with_config("muteOnStart") diff --git a/app/controllers/concerns/populator.rb b/app/controllers/concerns/populator.rb index a8df30d6..dd86d314 100644 --- a/app/controllers/concerns/populator.rb +++ b/app/controllers/concerns/populator.rb @@ -61,7 +61,7 @@ module Populator if user.present? # Find user and get his recordings rooms = User.find_by(email: user)&.rooms&.pluck(:bbb_id) - return all_recordings(rooms) if user.present? + return all_recordings(rooms) if user.present? && !rooms.nil? [] # return no recs if room not found elsif room.present? diff --git a/app/controllers/concerns/rolify.rb b/app/controllers/concerns/rolify.rb index f580ed2f..a49092f8 100644 --- a/app/controllers/concerns/rolify.rb +++ b/app/controllers/concerns/rolify.rb @@ -123,9 +123,10 @@ module Rolify :can_manage_rooms_recordings, :can_appear_in_share_list, :colour) permission_params.transform_values! do |v| - if v == "0" + case v + when "0" "false" - elsif v == "1" + when "1" "true" else v diff --git a/app/controllers/health_check_controller.rb b/app/controllers/health_check_controller.rb index 0c2fbb2d..8ecc0414 100644 --- a/app/controllers/health_check_controller.rb +++ b/app/controllers/health_check_controller.rb @@ -47,9 +47,7 @@ class HealthCheckController < ApplicationController end def database_check - if defined?(ActiveRecord) - raise "Database not responding" unless ActiveRecord::Migrator.current_version - end + raise "Database not responding" if defined?(ActiveRecord) && !ActiveRecord::Migrator.current_version raise "Pending migrations" unless ActiveRecord::Migration.check_pending!.nil? end @@ -61,9 +59,7 @@ class HealthCheckController < ApplicationController settings = ActionMailer::Base.smtp_settings smtp = Net::SMTP.new(settings[:address], settings[:port]) - if settings[:enable_starttls_auto] == "true" - smtp.enable_starttls_auto if smtp.respond_to?(:enable_starttls_auto) - end + smtp.enable_starttls_auto if settings[:enable_starttls_auto] == ("true") && smtp.respond_to?(:enable_starttls_auto) if settings[:authentication].present? && settings[:authentication] != "none" smtp.start(settings[:domain]) do |s| diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index c63d989f..fd4233c1 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -44,7 +44,9 @@ class RoomsController < ApplicationController 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 = Room.new(name: room_params[:name], + access_code: room_params[:access_code], + moderator_access_code: room_params[:moderator_access_code]) @room.owner = current_user @room.room_settings = create_room_settings_string(room_params) @@ -109,8 +111,9 @@ class RoomsController < ApplicationController @shared_room = room_shared_with_user unless @room.owned_by?(current_user) || @shared_room - # 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] + # Don't allow users to join unless they have a valid access code or the room doesn't have an access codes + valid_access_code = !@room.access_code.present? || @room.access_code == session[:access_code] + if !valid_access_code && !valid_moderator_access_code(session[:moderator_access_code]) return redirect_to room_path(room_uid: params[:room_uid]), flash: { alert: I18n.t("room.access_code_required") } end @@ -200,11 +203,17 @@ class RoomsController < ApplicationController # Update the rooms values room_settings_string = create_room_settings_string(options) - @room.update_attributes( + attributes = { name: options[:name], - room_settings: room_settings_string, - access_code: options[:access_code] - ) + } + + unless params[:setting] == "rename_header" + attributes[:room_settings] = room_settings_string + attributes[:access_code] = options[:access_code] + attributes[:moderator_access_code] = options[:moderator_access_code] + end + + @room.update(attributes) flash[:success] = I18n.t("room.update_settings_success") rescue => e @@ -321,9 +330,16 @@ class RoomsController < ApplicationController # POST /:room_uid/login def login - session[:access_code] = room_params[:access_code] + # use same form for access_code and moderator_access_code + if valid_moderator_access_code(room_params[:access_code]) + session[:moderator_access_code] = room_params[:access_code] + else + session[:access_code] = room_params[:access_code] + end - flash[:alert] = I18n.t("room.access_code_required") if session[:access_code] != @room.access_code + if session[:access_code] != @room.access_code && !valid_moderator_access_code(session[:moderator_access_code]) + flash[:alert] = I18n.t("room.access_code_required") + end redirect_to room_path(@room.uid) end @@ -332,11 +348,11 @@ class RoomsController < ApplicationController def create_room_settings_string(options) 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", - "recording": options[:recording] == "1", + muteOnStart: options[:mute_on_join] == "1", + requireModeratorApproval: options[:require_moderator_approval] == "1", + anyoneCanStart: options[:anyone_can_start] == "1", + joinModerator: options[:all_join_moderator] == "1", + recording: options[:recording] == "1", } room_settings.to_json @@ -345,7 +361,7 @@ class RoomsController < ApplicationController def room_params params.require(:room).permit(:name, :auto_join, :mute_on_join, :access_code, :require_moderator_approval, :anyone_can_start, :all_join_moderator, - :recording, :presentation) + :recording, :presentation, :moderator_access_code) end # Find the room from the uid. @@ -412,6 +428,11 @@ class RoomsController < ApplicationController end helper_method :room_limit_exceeded + def valid_moderator_access_code(code) + code == @room.moderator_access_code && !@room.moderator_access_code.blank? && moderator_code_allowed? + end + helper_method :valid_moderator_access_code + def record_meeting # If the require consent setting is checked, then check the room setting, else, set to true if recording_consent_required? diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index dcf014f2..2e04ac76 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -88,7 +88,10 @@ class SessionsController < ApplicationController # Check that the user is a Greenlight account return redirect_to(root_path, alert: I18n.t("invalid_login_method")) unless user.greenlight_account? # Check that the user has verified their account - return redirect_to(account_activation_path(digest: user.activation_digest)) unless user.activated? + unless user.activated? + user.create_activation_token if user.activation_digest.nil? + return redirect_to(account_activation_path(digest: user.activation_digest)) + end end login(user) @@ -125,13 +128,14 @@ class SessionsController < ApplicationController def ldap ldap_config = {} ldap_config[:host] = ENV['LDAP_SERVER'] - ldap_config[:port] = ENV['LDAP_PORT'].to_i != 0 ? ENV['LDAP_PORT'].to_i : 389 + ldap_config[:port] = ENV['LDAP_PORT'].to_i.zero? ? 389 : ENV['LDAP_PORT'].to_i ldap_config[:bind_dn] = ENV['LDAP_BIND_DN'] ldap_config[:password] = ENV['LDAP_PASSWORD'] ldap_config[:auth_method] = ENV['LDAP_AUTH'] - ldap_config[:encryption] = if ENV['LDAP_METHOD'] == 'ssl' + ldap_config[:encryption] = case ENV['LDAP_METHOD'] + when 'ssl' 'simple_tls' - elsif ENV['LDAP_METHOD'] == 'tls' + when 'tls' 'start_tls' end ldap_config[:base] = ENV['LDAP_BASE'] diff --git a/app/helpers/admins_helper.rb b/app/helpers/admins_helper.rb index 91f3a2e7..f21f877b 100644 --- a/app/helpers/admins_helper.rb +++ b/app/helpers/admins_helper.rb @@ -89,6 +89,14 @@ module AdminsHelper end end + def moderator_codes_string + if @settings.get_value("Moderator Access Codes") == "true" + I18n.t("administrator.site_settings.moderator_codes.enabled") + else + I18n.t("administrator.site_settings.moderator_codes.disabled") + end + end + def log_level_string case Rails.logger.level when 0 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 5691cedf..238cddf3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -58,30 +58,24 @@ module ApplicationHelper # 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]) + return "active" if controller_name == "admins" && action_name == "index" && current_user.has_role?(:super_admin) + return "active" if controller_name == "rooms" && home_actions.include?(action_name) "" 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 def translated_role_name(role) - if role.name == "denied" + case role.name + when "denied" I18n.t("roles.banned") - elsif role.name == "pending" + when "pending" I18n.t("roles.pending") - elsif role.name == "admin" + when "admin" I18n.t("roles.admin") - elsif role.name == "user" + when "user" I18n.t("roles.user") else role.name @@ -109,6 +103,8 @@ module ApplicationHelper # Make a GET request and validate content type http = Net::HTTP.new(url.host, url.port) http.use_ssl = (url.scheme == "https") + http.read_timeout = 10 + http.open_timeout = 10 http.start do |web| response = web.head(url.request_uri) diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 1d691d49..7cc01984 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -44,7 +44,7 @@ module UsersHelper # Returns language selection options for user edit def language_options locales = I18n.available_locales - language_opts = [['<<<< ' + t("language_default") + ' >>>>', "default"]] + 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]) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index f7ac797a..c8470e14 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -43,7 +43,7 @@ class UserMailer < ApplicationMailer def user_promoted(user, role, url, settings) @settings = settings @url = url - @admin_url = url + "admins" + @admin_url = "#{url}admins" @image = logo_image @color = user_color @role = translated_role_name(role) @@ -64,13 +64,14 @@ class UserMailer < ApplicationMailer mail to: user.email, subject: t('mailer.user.demoted.subtitle', role: translated_role_name(role)) end - def invite_email(name, email, url, settings) + def invite_email(name, email, invite_date, url, settings) @settings = settings @name = name @email = email @url = url @image = logo_image @color = user_color + @date = "#{(invite_date + 2.days).strftime('%b %d, %Y %-I:%M%P')} UTC" mail to: email, subject: t('mailer.user.invite.subject') end diff --git a/app/models/setting.rb b/app/models/setting.rb index 1ee18192..69ec3995 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -66,6 +66,8 @@ class Setting < ApplicationRecord Rails.configuration.shared_access_default when "Preupload Presentation" Rails.configuration.preupload_presentation_default + when "Room Configuration Moderator Access Codes" + Rails.configuration.moderator_codes_default when "Room Configuration Mute On Join" room_config_setting("mute-on-join") when "Room Configuration Require Moderator" diff --git a/app/models/user.rb b/app/models/user.rb index 66f6fc31..679cbdd1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -41,7 +41,7 @@ class User < ApplicationRecord validate :check_if_email_can_be_blank validates :email, length: { maximum: 256 }, allow_blank: true, uniqueness: { case_sensitive: false, scope: :provider }, - format: { with: /\A[\w+\-\'.]+@[a-z\d\-.]+\.[a-z]+\z/i } + format: { with: /\A[\w+\-'.]+@[a-z\d\-.]+\.[a-z]+\z/i } validates :password, length: { minimum: 6 }, confirmation: true, if: :greenlight_account?, on: :create diff --git a/app/views/admins/components/_menu_buttons.html.erb b/app/views/admins/components/_menu_buttons.html.erb index 858a1bf7..d4c0e4dd 100644 --- a/app/views/admins/components/_menu_buttons.html.erb +++ b/app/views/admins/components/_menu_buttons.html.erb @@ -17,29 +17,29 @@ <% 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 %> - <%= t("administrator.users.title") %> + <%= link_to admins_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if action_name == "index"}" do %> + <%= t("administrator.users.title") %> <% end %> <% end %> <% if highest_role.get_permission("can_manage_rooms_recordings") || highest_role.name == "super_admin" %> - <%= link_to admin_rooms_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "server_rooms"}" do %> - <%= t("administrator.rooms.title") %> + <%= link_to admin_rooms_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if action_name == "server_rooms"}" do %> + <%= t("administrator.rooms.title") %> <% end %> - <%= 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") %> + <%= link_to admin_recordings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if action_name == "server_recordings"}" do %> + <%= t("administrator.recordings.title") %> <% end %> <% end %> <% if highest_role.get_permission("can_edit_site_settings") || highest_role.name == "super_admin" %> - <%= link_to admin_site_settings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "site_settings"}" do %> - <%= t("administrator.site_settings.title") %> + <%= link_to admin_site_settings_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if action_name == "site_settings"}" do %> + <%= t("administrator.site_settings.title") %> <% end %> - <%= link_to admin_room_configuration_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if active_page == "room_configuration"}" do %> - <%= t("administrator.room_configuration.title") %> + <%= link_to admin_room_configuration_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if action_name == "room_configuration"}" do %> + <%= t("administrator.room_configuration.title") %> <% end %> <% end %> <% 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") %> + <%= link_to admin_roles_path, class: "list-group-item list-group-item-action dropdown-item #{"active" if action_name == "roles"}" do %> + <%= t("administrator.roles.title") %> <% end %> <% end %> \ No newline at end of file diff --git a/app/views/admins/components/_room_settings.html.erb b/app/views/admins/components/_room_settings.html.erb index 53d37046..d81e4606 100644 --- a/app/views/admins/components/_room_settings.html.erb +++ b/app/views/admins/components/_room_settings.html.erb @@ -124,5 +124,26 @@ <% end %> +