diff --git a/.travis.yml b/.travis.yml index c17424e5..554ab12c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ before_install: - docker pull openhpi/co_execenv_python - docker pull openhpi/co_execenv_java - mkdir ~/geckodriver - - wget -O ~/geckodriver/download.tar.gz https://github.com/mozilla/geckodriver/releases/download/v0.18.0/geckodriver-v0.18.0-linux64.tar.gz + - wget -O ~/geckodriver/download.tar.gz https://github.com/mozilla/geckodriver/releases/download/v0.21.0/geckodriver-v0.21.0-linux64.tar.gz - tar -xvzf ~/geckodriver/download.tar.gz -C ~/geckodriver/ - rm ~/geckodriver/download.tar.gz - chmod +x ~/geckodriver/geckodriver @@ -39,6 +39,6 @@ before_script: cache: bundler language: ruby rvm: -- 2.3.6 +- 2.5.1 script: bundle exec rspec --color --format documentation --require spec_helper --require rails_helper && bundle exec codeclimate-test-reporter diff --git a/Gemfile b/Gemfile index 34ffb8b7..ed019814 100644 --- a/Gemfile +++ b/Gemfile @@ -14,11 +14,11 @@ gem 'jquery-turbolinks' gem 'ims-lti', '< 2.0.0' gem 'kramdown' gem 'newrelic_rpm' -gem 'pg', '< 1.0', platform: :ruby +gem 'pg' gem 'pry-byebug' gem 'puma' gem 'pundit' -gem 'rails', '4.2.10' +gem 'rails', '5.2.1' gem 'rails-i18n' gem 'ransack' gem 'rubytree' @@ -28,19 +28,20 @@ gem 'bootstrap_pagedown' gem 'sorcery' gem 'turbolinks', '< 5.0.0' # newer versions prevent loading ACE if the page containing is not accessed directly / refreshed gem 'uglifier' -gem 'tubesock' +gem 'tubesock', git: 'https://github.com/gosukiwi/tubesock', branch: 'patch-1' # Switch to a fork which is compatible with Rails 5 gem 'faye-websocket' -gem 'eventmachine', '1.0.9.1' # explicitly added, this is used by faye-websocket, version 1.2.5 still has an error in eventmachine.rb:202: [BUG] Segmentation fault, which is not yet fixed and causes the whole ruby process to crash gem 'nokogiri' -gem 'd3-rails', '~>4.0' +gem 'd3-rails' gem 'rest-client' gem 'rubyzip' gem 'mnemosyne-ruby' gem 'whenever', require: false group :development, :staging do - gem 'better_errors', platform: :ruby - gem 'binding_of_caller', platform: :ruby + gem 'bootsnap', require: false + gem 'listen' + gem 'better_errors' + gem 'binding_of_caller' gem 'capistrano' gem 'capistrano3-puma' gem 'capistrano-rails' @@ -49,7 +50,7 @@ group :development, :staging do gem 'rack-mini-profiler' gem 'rubocop', require: false gem 'rubocop-rspec' - gem 'web-console', platform: :ruby + gem 'web-console' end group :development, :test, :staging do @@ -57,6 +58,7 @@ group :development, :test, :staging do end group :test do + gem 'rails-controller-testing' gem 'autotest-rails' gem 'capybara' gem 'selenium-webdriver' diff --git a/Gemfile.lock b/Gemfile.lock index 26f12f09..bfafa8f5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,47 +1,63 @@ +GIT + remote: https://github.com/gosukiwi/tubesock + revision: 86a5ca4f7d3c3a7b9a727ad91df3b9b4912eda39 + branch: patch-1 + specs: + tubesock (0.2.7) + rack (>= 1.5.0) + websocket (>= 1.1.0) + GEM remote: https://rubygems.org/ specs: ZenTest (4.11.1) - actionmailer (4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) + actioncable (5.2.1) + actionpack (= 5.2.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.10) - actionview (= 4.2.10) - activesupport (= 4.2.10) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) + actionpack (5.2.1) + actionview (= 5.2.1) + activesupport (= 5.2.1) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.10) - activesupport (= 4.2.10) + actionview (5.2.1) + activesupport (= 5.2.1) builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (4.2.10) - activesupport (= 4.2.10) - globalid (>= 0.3.0) - activemodel (4.2.10) - activesupport (= 4.2.10) - builder (~> 3.1) - activerecord (4.2.10) - activemodel (= 4.2.10) - activesupport (= 4.2.10) - arel (~> 6.0) - activesupport (4.2.10) - i18n (~> 0.7) + activejob (5.2.1) + activesupport (= 5.2.1) + globalid (>= 0.3.6) + activemodel (5.2.1) + activesupport (= 5.2.1) + activerecord (5.2.1) + activemodel (= 5.2.1) + activesupport (= 5.2.1) + arel (>= 9.0) + activestorage (5.2.1) + actionpack (= 5.2.1) + activerecord (= 5.2.1) + marcel (~> 0.3.1) + activesupport (5.2.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) airbrussh (1.3.0) sshkit (>= 1.6.1, != 1.7.0) amq-protocol (2.3.0) - arel (6.0.4) + arel (9.0.0) ast (2.4.0) autotest-rails (4.2.1) ZenTest (~> 4.5) @@ -50,8 +66,11 @@ GEM coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) + bindex (0.5.0) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) + bootsnap (1.3.2) + msgpack (~> 1.0) bootstrap-will_paginate (1.0.0) will_paginate bootstrap_pagedown (1.1.0) @@ -80,7 +99,7 @@ GEM capistrano (~> 3.7) capistrano-bundler puma (~> 3.4) - capybara (3.7.1) + capybara (3.7.2) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) @@ -94,8 +113,8 @@ GEM childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) chronic (0.10.2) - codeclimate-test-reporter (1.0.7) - simplecov + codeclimate-test-reporter (1.0.8) + simplecov (<= 0.13) coderay (1.1.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) @@ -106,20 +125,19 @@ GEM coffee-script-source (1.12.2) concurrent-ruby (1.0.5) crass (1.0.4) - d3-rails (4.13.0) + d3-rails (5.5.0) railties (>= 3.1) database_cleaner (1.7.0) debug_inspector (0.0.3) diff-lcs (1.3) - docile (1.3.1) + docile (1.1.5) docker-api (1.34.2) excon (>= 0.47.0) multi_json domain_name (0.5.20180417) unf (>= 0.0.5, < 1.0.0) erubi (1.7.1) - erubis (2.7.0) - eventmachine (1.0.9.1) + eventmachine (1.2.7) excon (0.62.0) execjs (2.7.0) factory_bot (4.11.1) @@ -140,7 +158,7 @@ GEM highline (2.0.0) http-cookie (1.0.3) domain_name (~> 0.5) - i18n (0.9.5) + i18n (1.1.0) concurrent-ruby (~> 1.0) ims-lti (1.2.2) builder @@ -159,21 +177,29 @@ GEM json (2.1.0) jwt (1.5.6) kramdown (1.17.0) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) method_source (0.9.0) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2018.0812) + mimemagic (0.3.2) mini_mime (1.0.1) mini_portile2 (2.3.0) minitest (5.11.3) mnemosyne-ruby (1.5.1) activesupport (>= 4) bunny + msgpack (1.2.4) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) @@ -181,7 +207,8 @@ GEM net-ssh (>= 2.6.5) net-ssh (5.0.2) netrc (0.11.0) - newrelic_rpm (5.3.0.346) + newrelic_rpm (5.4.0.347) + nio4r (2.3.1) nokogiri (1.8.4) mini_portile2 (~> 2.3.0) nyan-cat-formatter (0.12.0) @@ -196,7 +223,7 @@ GEM parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) - pg (0.21.0) + pg (1.1.3) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) @@ -208,44 +235,48 @@ GEM puma (3.12.0) pundit (2.0.0) activesupport (>= 3.0.0) - rack (1.6.10) + rack (2.0.5) rack-mini-profiler (1.0.0) rack (>= 1.2.0) - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.10) - actionmailer (= 4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) - activemodel (= 4.2.10) - activerecord (= 4.2.10) - activesupport (= 4.2.10) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.10) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.9) - activesupport (>= 4.2.0, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (5.2.1) + actioncable (= 5.2.1) + actionmailer (= 5.2.1) + actionpack (= 5.2.1) + actionview (= 5.2.1) + activejob (= 5.2.1) + activemodel (= 5.2.1) + activerecord (= 5.2.1) + activestorage (= 5.2.1) + activesupport (= 5.2.1) + bundler (>= 1.3.0) + railties (= 5.2.1) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) + 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) - rails-i18n (4.0.9) - i18n (~> 0.7) - railties (~> 4.0) - railties (4.2.10) - actionpack (= 4.2.10) - activesupport (= 4.2.10) + rails-i18n (5.1.1) + i18n (>= 0.7, < 2) + railties (>= 5.0, < 6) + railties (5.2.1) + actionpack (= 5.2.1) + activesupport (= 5.2.1) + method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (12.3.1) - ransack (1.8.9) - actionpack (>= 3.0, <= 5.1.1) - activerecord (>= 3.0, <= 5.1.1) - activesupport (>= 3.0, <= 5.1.1) + ransack (2.0.1) + actionpack (>= 5.0) + activerecord (>= 5.0) + activesupport (>= 5.0) i18n rb-fsevent (0.10.3) rb-inotify (0.9.10) @@ -277,7 +308,7 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.0) - rubocop (0.59.0) + rubocop (0.59.1) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.5, != 2.5.1.1) @@ -288,6 +319,7 @@ GEM rubocop-rspec (1.29.1) rubocop (>= 0.58.0) ruby-progressbar (1.10.0) + ruby_dep (1.5.0) rubytree (1.0.0) json (~> 2.1) structured_warnings (~> 0.3) @@ -306,8 +338,8 @@ GEM selenium-webdriver (3.14.0) childprocess (~> 0.5) rubyzip (~> 1.2) - simplecov (0.16.1) - docile (~> 1.1) + simplecov (0.13.0) + docile (~> 1.1.0) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) @@ -339,23 +371,21 @@ GEM thor (0.20.0) thread_safe (0.3.6) tilt (2.0.8) - tubesock (0.2.7) - rack (>= 1.5.0) - websocket (>= 1.1.0) turbolinks (2.5.4) coffee-rails tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.18) + uglifier (4.1.19) execjs (>= 0.3.0, < 3) unf (0.1.4) unf_ext unf_ext (0.0.7.5) unicode-display_width (1.4.0) - web-console (3.3.0) - activemodel (>= 4.2) - debug_inspector - railties (>= 4.2) + web-console (3.7.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) websocket (1.2.8) websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) @@ -374,6 +404,7 @@ DEPENDENCIES bcrypt better_errors binding_of_caller + bootsnap bootstrap-will_paginate bootstrap_pagedown capistrano @@ -385,10 +416,9 @@ DEPENDENCIES carrierwave codeclimate-test-reporter concurrent-ruby - d3-rails (~> 4.0) + d3-rails database_cleaner docker-api - eventmachine (= 1.0.9.1) factory_bot_rails faye-websocket forgery @@ -399,16 +429,18 @@ DEPENDENCIES jquery-rails jquery-turbolinks kramdown + listen mnemosyne-ruby newrelic_rpm nokogiri nyan-cat-formatter - pg (< 1.0) + pg pry-byebug puma pundit rack-mini-profiler - rails (= 4.2.10) + rails (= 5.2.1) + rails-controller-testing rails-i18n ransack rest-client @@ -424,11 +456,11 @@ DEPENDENCIES slim-rails sorcery spring - tubesock + tubesock! turbolinks (< 5.0.0) uglifier web-console whenever BUNDLED WITH - 1.16.3 + 1.16.5 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 22b06a61..e05263f4 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -11,16 +11,23 @@ // about supported directives. // //= require jquery -// -//= require ace/ace -//= require chosen.jquery.min -//= require jquery-ui.min -//= require d3 //= require jquery.turbolinks //= require jquery_ujs -//= require jstree/jstree.min -//= require turbolinks -//= require_tree ../../../lib -//= require_tree . //= require bootstrap_pagedown -//= require ace/ext-language_tools \ No newline at end of file +//= require d3 +//= require turbolinks +// +// lib/assets +//= require flash +//= require url +// +// vendor/assets +//= require ace/ace +//= require ace/ext-language_tools +//= require jstree/jstree.min +//= require bootstrap.min +//= require chosen.jquery.min +//= require jquery-ui.min +//= require underscore.min +//= require vis.min +//= require_tree . diff --git a/app/assets/javascripts/dashboard.js b/app/assets/javascripts/dashboard.js index ed7c5b68..76ad804e 100644 --- a/app/assets/javascripts/dashboard.js +++ b/app/assets/javascripts/dashboard.js @@ -51,6 +51,7 @@ $(function() { } else { var jqxhr = $.ajax({ dataType: 'json', + url: 'dashboard', method: 'GET' }); jqxhr.done(function(response) { diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index e21a40df..5ba3be40 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -10,9 +10,19 @@ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new * file per style scope. * - *= require_tree . - *= require_tree ../../../lib - *= require_tree ../../../vendor/assets/stylesheets/ - *= require_self *= require bootstrap_pagedown + * + * lib/assets + *= require flash + * + * vendor/assets + *= require bootstrap.min + *= require chosen.min + *= require font-awesome.min + *= require google_opensans + *= require jquery-ui.min + *= require jquery-ui.structure.min + *= require style.min + *= require vis.min + *= require_tree . */ diff --git a/app/controllers/code_ocean/files_controller.rb b/app/controllers/code_ocean/files_controller.rb index a788e4df..dbced0b7 100644 --- a/app/controllers/code_ocean/files_controller.rb +++ b/app/controllers/code_ocean/files_controller.rb @@ -41,7 +41,7 @@ module CodeOcean end def file_params - params[:code_ocean_file].permit(file_attributes).merge(context_type: 'Submission', role: 'user_defined_file') + params[:code_ocean_file].permit(file_attributes).merge(context_type: 'Submission', role: 'user_defined_file') if params[:code_ocean_file].present? end private :file_params end diff --git a/app/controllers/concerns/lti.rb b/app/controllers/concerns/lti.rb index 4ba93615..e8241af3 100644 --- a/app/controllers/concerns/lti.rb +++ b/app/controllers/concerns/lti.rb @@ -23,9 +23,9 @@ module Lti session.delete(:consumer_id) session.delete(:external_user_id) else - LtiParameter.destroy_all(consumers_id: consumer_id, - external_users_id: user_id, - exercises_id: exercise_id) + LtiParameter.where(consumers_id: consumer_id, + external_users_id: user_id, + exercises_id: exercise_id).destroy_all end end private :clear_lti_session_data @@ -138,7 +138,7 @@ module Lti external_users_id: @current_user.id, exercises_id: @exercise.id) - lti_parameters.lti_parameters = options[:parameters].slice(*SESSION_PARAMETERS).to_json + lti_parameters.lti_parameters = options[:parameters].slice(*SESSION_PARAMETERS).permit!.to_h lti_parameters.save! @lti_parameters = lti_parameters diff --git a/app/controllers/concerns/remote_evaluation_parameters.rb b/app/controllers/concerns/remote_evaluation_parameters.rb index 4f0acab2..a88ef7ea 100644 --- a/app/controllers/concerns/remote_evaluation_parameters.rb +++ b/app/controllers/concerns/remote_evaluation_parameters.rb @@ -2,7 +2,7 @@ module RemoteEvaluationParameters include FileParameters def remote_evaluation_params - remote_evaluation_params = params[:remote_evaluation].permit(:validation_token, files_attributes: file_attributes) + remote_evaluation_params = params[:remote_evaluation].permit(:validation_token, files_attributes: file_attributes) if params[:remote_evaluation].present? end private :remote_evaluation_params end \ No newline at end of file diff --git a/app/controllers/concerns/submission_parameters.rb b/app/controllers/concerns/submission_parameters.rb index 6b1781b3..fa5c848b 100644 --- a/app/controllers/concerns/submission_parameters.rb +++ b/app/controllers/concerns/submission_parameters.rb @@ -16,7 +16,7 @@ module SubmissionParameters current_user_id = current_user.id current_user_class_name = current_user.class.name end - submission_params = params[:submission].permit(:cause, :exercise_id, files_attributes: file_attributes).merge(user_id: current_user_id, user_type: current_user_class_name) + submission_params = params[:submission].present? ? params[:submission].permit(:cause, :exercise_id, files_attributes: file_attributes).merge(user_id: current_user_id, user_type: current_user_class_name) : {} reject_illegal_file_attributes!(submission_params) submission_params end diff --git a/app/controllers/consumers_controller.rb b/app/controllers/consumers_controller.rb index 5c97a58a..2a2f784a 100644 --- a/app/controllers/consumers_controller.rb +++ b/app/controllers/consumers_controller.rb @@ -22,7 +22,7 @@ class ConsumersController < ApplicationController end def consumer_params - params[:consumer].permit(:name, :oauth_key, :oauth_secret) + params[:consumer].permit(:name, :oauth_key, :oauth_secret) if params[:consumer].present? end private :consumer_params diff --git a/app/controllers/error_template_attributes_controller.rb b/app/controllers/error_template_attributes_controller.rb index 05de2772..283e5b03 100644 --- a/app/controllers/error_template_attributes_controller.rb +++ b/app/controllers/error_template_attributes_controller.rb @@ -81,6 +81,6 @@ class ErrorTemplateAttributesController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def error_template_attribute_params - params[:error_template_attribute].permit(:key, :description, :regex, :important) + params[:error_template_attribute].permit(:key, :description, :regex, :important) if params[:error_template_attribute].present? end end diff --git a/app/controllers/error_templates_controller.rb b/app/controllers/error_templates_controller.rb index 2632abf9..bec956d8 100644 --- a/app/controllers/error_templates_controller.rb +++ b/app/controllers/error_templates_controller.rb @@ -99,6 +99,6 @@ class ErrorTemplatesController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def error_template_params - params[:error_template].permit(:name, :execution_environment_id, :signature, :description, :hint) + params[:error_template].permit(:name, :execution_environment_id, :signature, :description, :hint) if params[:error_template].present? end end diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 667b186d..6a843eeb 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -15,14 +15,14 @@ class ErrorsController < ApplicationController if hint render(json: {hint: hint}) else - render(nothing: true, status: @error.save ? :created : :unprocessable_entity) + head (@error.save ? :created : :unprocessable_entity) end end end end def error_params - params[:error].permit(:message, :submission_id).merge(execution_environment_id: @execution_environment.id) + params[:error].permit(:message, :submission_id).merge(execution_environment_id: @execution_environment.id) if params[:error].present? end private :error_params diff --git a/app/controllers/execution_environments_controller.rb b/app/controllers/execution_environments_controller.rb index c220ae74..917c9f5f 100644 --- a/app/controllers/execution_environments_controller.rb +++ b/app/controllers/execution_environments_controller.rb @@ -86,11 +86,11 @@ class ExecutionEnvironmentsController < ApplicationController working_time_statistics = {} user_statistics = {} - ActiveRecord::Base.connection.execute(working_time_query).each do |tuple| + ApplicationRecord.connection.execute(working_time_query).each do |tuple| working_time_statistics[tuple["exercise_id"].to_i] = tuple end - ActiveRecord::Base.connection.execute(user_query).each do |tuple| + ApplicationRecord.connection.execute(user_query).each do |tuple| user_statistics[tuple["exercise_id"].to_i] = tuple end @@ -101,7 +101,7 @@ class ExecutionEnvironmentsController < ApplicationController end def execution_environment_params - params[:execution_environment].permit(:docker_image, :exposed_ports, :editor_mode, :file_extension, :file_type_id, :help, :indent_size, :memory_limit, :name, :network_enabled, :permitted_execution_time, :pool_size, :run_command, :test_command, :testing_framework).merge(user_id: current_user.id, user_type: current_user.class.name) + params[:execution_environment].permit(:docker_image, :exposed_ports, :editor_mode, :file_extension, :file_type_id, :help, :indent_size, :memory_limit, :name, :network_enabled, :permitted_execution_time, :pool_size, :run_command, :test_command, :testing_framework).merge(user_id: current_user.id, user_type: current_user.class.name) if params[:execution_environment].present? end private :execution_environment_params diff --git a/app/controllers/exercise_collections_controller.rb b/app/controllers/exercise_collections_controller.rb index cfb93a71..3e13a3af 100644 --- a/app/controllers/exercise_collections_controller.rb +++ b/app/controllers/exercise_collections_controller.rb @@ -51,7 +51,7 @@ class ExerciseCollectionsController < ApplicationController end def exercise_collection_params - sanitized_params = params[:exercise_collection].permit(:name, :use_anomaly_detection, :user_id, :user_type, :exercise_ids => []).merge(user_type: InternalUser.name) + sanitized_params = params[:exercise_collection].present? ? params[:exercise_collection].permit(:name, :use_anomaly_detection, :user_id, :user_type, :exercise_ids => []).merge(user_type: InternalUser.name) : {} sanitized_params[:exercise_ids] = sanitized_params[:exercise_ids].reject {|v| v.nil? or v == ''} sanitized_params.tap {|p| p[:exercise_collection_items] = p[:exercise_ids].map.with_index {|_id, index| ExerciseCollectionItem.find_or_create_by(exercise_id: _id, exercise_collection_id: @exercise_collection.id, position: index)}; p.delete(:exercise_ids)} end diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index b506afdf..72b5ce2f 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -12,9 +12,9 @@ class ExercisesController < ApplicationController before_action :set_file_types, only: [:create, :edit, :new, :update] before_action :set_course_token, only: [:implement] - skip_before_filter :verify_authenticity_token, only: [:import_proforma_xml] + skip_before_action :verify_authenticity_token, only: [:import_proforma_xml] skip_after_action :verify_authorized, only: [:import_proforma_xml] - skip_after_action :verify_policy_scoped, only: [:import_proforma_xml] + skip_after_action :verify_policy_scoped, only: [:import_proforma_xml], raise: false def authorize! authorize(@exercise || @exercises) @@ -77,7 +77,7 @@ class ExercisesController < ApplicationController def create @exercise = Exercise.new(exercise_params) collect_set_and_unset_exercise_tags - myparam = exercise_params + myparam = exercise_params.present? ? exercise_params : { } checked_exercise_tags = @exercise_tags.select { | et | myparam[:tag_ids].include? et.tag.id.to_s } removed_exercise_tags = @exercise_tags.reject { | et | myparam[:tag_ids].include? et.tag.id.to_s } @@ -160,19 +160,21 @@ class ExercisesController < ApplicationController private :user_by_code_harbor_token def exercise_params - params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :hide_file_tree, :allow_file_creation, :allow_auto_completion, :title, :expected_difficulty, files_attributes: file_attributes, :tag_ids => []).merge(user_id: current_user.id, user_type: current_user.class.name) + params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :hide_file_tree, :allow_file_creation, :allow_auto_completion, :title, :expected_difficulty, files_attributes: file_attributes, :tag_ids => []).merge(user_id: current_user.id, user_type: current_user.class.name) if params[:exercise].present? end private :exercise_params def handle_file_uploads - exercise_params[:files_attributes].try(:each) do |index, file_attributes| - if file_attributes[:content].respond_to?(:read) - file_params = params[:exercise][:files_attributes][index] - if FileType.find_by(id: file_attributes[:file_type_id]).try(:binary?) - file_params[:content] = nil - file_params[:native_file] = file_attributes[:content] - else - file_params[:content] = file_attributes[:content].read + if exercise_params + exercise_params[:files_attributes].try(:each) do |index, file_attributes| + if file_attributes[:content].respond_to?(:read) + file_params = params[:exercise][:files_attributes][index] + if FileType.find_by(id: file_attributes[:file_type_id]).try(:binary?) + file_params[:content] = nil + file_params[:native_file] = file_attributes[:content] + else + file_params[:content] = file_attributes[:content].read + end end end end @@ -364,7 +366,7 @@ class ExercisesController < ApplicationController query = "SELECT user_id, MAX(score) AS maximum_score, COUNT(id) AS runs FROM submissions WHERE exercise_id = #{@exercise.id} GROUP BY user_id;" - ActiveRecord::Base.connection.execute(query).each do |tuple| + ApplicationRecord.connection.execute(query).each do |tuple| user_statistics[tuple["user_id"].to_i] = tuple end render locals: { diff --git a/app/controllers/external_users_controller.rb b/app/controllers/external_users_controller.rb index 441edd67..503d323f 100644 --- a/app/controllers/external_users_controller.rb +++ b/app/controllers/external_users_controller.rb @@ -57,7 +57,7 @@ class ExternalUsersController < ApplicationController statistics = {} - ActiveRecord::Base.connection.execute(working_time_query(params[:tag])).each do |tuple| + ApplicationRecord.connection.execute(working_time_query(params[:tag])).each do |tuple| statistics[tuple["exercise_id"].to_i] = tuple end diff --git a/app/controllers/file_templates_controller.rb b/app/controllers/file_templates_controller.rb index a6039500..04c2a98a 100644 --- a/app/controllers/file_templates_controller.rb +++ b/app/controllers/file_templates_controller.rb @@ -89,6 +89,6 @@ class FileTemplatesController < ApplicationController # Never trust parameters from the scary internet, only allow the white list through. def file_template_params - params[:file_template].permit(:name, :file_type_id, :content) + params[:file_template].permit(:name, :file_type_id, :content) if params[:file_template].present? end end diff --git a/app/controllers/file_types_controller.rb b/app/controllers/file_types_controller.rb index 9f16da28..8f29b72b 100644 --- a/app/controllers/file_types_controller.rb +++ b/app/controllers/file_types_controller.rb @@ -23,7 +23,7 @@ class FileTypesController < ApplicationController end def file_type_params - params[:file_type].permit(:binary, :editor_mode, :executable, :file_extension, :name, :indent_size, :renderable).merge(user_id: current_user.id, user_type: current_user.class.name) + params[:file_type].permit(:binary, :editor_mode, :executable, :file_extension, :name, :indent_size, :renderable).merge(user_id: current_user.id, user_type: current_user.class.name) if params[:file_type].present? end private :file_type_params diff --git a/app/controllers/hints_controller.rb b/app/controllers/hints_controller.rb index 827ba6ce..48b86b63 100644 --- a/app/controllers/hints_controller.rb +++ b/app/controllers/hints_controller.rb @@ -23,7 +23,7 @@ class HintsController < ApplicationController end def hint_params - params[:hint].permit(:locale, :message, :name, :regular_expression).merge(execution_environment_id: @execution_environment.id) + params[:hint].permit(:locale, :message, :name, :regular_expression).merge(execution_environment_id: @execution_environment.id) if params[:hint].present? end private :hint_params diff --git a/app/controllers/internal_users_controller.rb b/app/controllers/internal_users_controller.rb index b9efb276..6779cff5 100644 --- a/app/controllers/internal_users_controller.rb +++ b/app/controllers/internal_users_controller.rb @@ -21,7 +21,7 @@ class InternalUsersController < ApplicationController if @user.update(params[:internal_user].permit(:password, :password_confirmation)) @user.change_password!(params[:internal_user][:password]) format.html { redirect_to(sign_in_path, notice: t('.success')) } - format.json { render(nothing: true, status: :ok) } + format.json { head :ok } else respond_with_invalid_object(format, object: @user, template: :reset_password) end @@ -66,7 +66,7 @@ class InternalUsersController < ApplicationController end def internal_user_params - params[:internal_user].permit(:consumer_id, :email, :name, :role) + params[:internal_user].permit(:consumer_id, :email, :name, :role) if params[:internal_user].present? end private :internal_user_params @@ -105,7 +105,7 @@ class InternalUsersController < ApplicationController if @user.update(params[:internal_user].permit(:password, :password_confirmation)) @user.activate! format.html { redirect_to(sign_in_path, notice: t('.success')) } - format.json { render(nothing: true, status: :ok) } + format.json { head :ok } else respond_with_invalid_object(format, object: @user, template: :activate) end diff --git a/app/controllers/interventions_controller.rb b/app/controllers/interventions_controller.rb index b4b5971e..27bfe4e0 100644 --- a/app/controllers/interventions_controller.rb +++ b/app/controllers/interventions_controller.rb @@ -22,7 +22,7 @@ class InterventionsController < ApplicationController end def intervention_params - params[:intervention].permit(:name) + params[:intervention].permit(:name) if params[:intervention].present? end private :intervention_params diff --git a/app/controllers/proxy_exercises_controller.rb b/app/controllers/proxy_exercises_controller.rb index 02fe0220..40bd20ca 100644 --- a/app/controllers/proxy_exercises_controller.rb +++ b/app/controllers/proxy_exercises_controller.rb @@ -39,7 +39,7 @@ class ProxyExercisesController < ApplicationController end def proxy_exercise_params - params[:proxy_exercise].permit(:description, :title, :exercise_ids => []) + params[:proxy_exercise].permit(:description, :title, :exercise_ids => []) if params[:proxy_exercise].present? end private :proxy_exercise_params diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 1624e5e0..0e37dd07 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -115,7 +115,7 @@ class SubmissionsController < ApplicationController if @file.native_file? send_file(@file.native_file.path, disposition: 'inline') else - render(text: @file.content) + render(plain: @file.content) end end @@ -140,7 +140,7 @@ class SubmissionsController < ApplicationController # probably add: # ensure # #guarantee that the thread is releasing the DB connection after it is done - # ActiveRecord::Base.connectionpool.releaseconnection + # ApplicationRecord.connectionpool.releaseconnection # end Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive? @@ -329,7 +329,7 @@ class SubmissionsController < ApplicationController def set_file @file = @files.detect { |file| file.name_with_extension == params[:filename] } - render(nothing: true, status: 404) unless @file + head :not_found unless @file end private :set_file @@ -362,7 +362,7 @@ class SubmissionsController < ApplicationController DockerClient.destroy_container(container) rescue Docker::Error::NotFoundError ensure - render(nothing: true) + head :ok end def store_error(stderr) diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb index 232e9f01..f86431e2 100644 --- a/app/controllers/subscriptions_controller.rb +++ b/app/controllers/subscriptions_controller.rb @@ -56,7 +56,7 @@ class SubscriptionsController < ApplicationController def subscription_params current_user_id = current_user.try(:id) current_user_class_name = current_user.try(:class).try(:name) - params[:subscription].permit(:request_for_comment_id, :subscription_type).merge(user_id: current_user_id, user_type: current_user_class_name, deleted: false) + params[:subscription].permit(:request_for_comment_id, :subscription_type).merge(user_id: current_user_id, user_type: current_user_class_name, deleted: false) if params[:subscription].present? end private :subscription_params end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index ff6925dd..ac462653 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -22,7 +22,7 @@ class TagsController < ApplicationController end def tag_params - params[:tag].permit(:name) + params[:tag].permit(:name) if params[:tag].present? end private :tag_params diff --git a/app/controllers/user_exercise_feedbacks_controller.rb b/app/controllers/user_exercise_feedbacks_controller.rb index 4c350a81..841357e1 100644 --- a/app/controllers/user_exercise_feedbacks_controller.rb +++ b/app/controllers/user_exercise_feedbacks_controller.rb @@ -112,7 +112,7 @@ class UserExerciseFeedbacksController < ApplicationController end def uef_params - params[:user_exercise_feedback].permit(:feedback_text, :difficulty, :exercise_id, :user_estimated_worktime).merge(user_id: current_user.id, user_type: current_user.class.name) + params[:user_exercise_feedback].permit(:feedback_text, :difficulty, :exercise_id, :user_estimated_worktime).merge(user_id: current_user.id, user_type: current_user.class.name) if params[:user_exercise_feedback].present? end def validate_inputs(uef_params) diff --git a/app/helpers/lti_helper.rb b/app/helpers/lti_helper.rb index 433468a1..f4a37650 100644 --- a/app/helpers/lti_helper.rb +++ b/app/helpers/lti_helper.rb @@ -1,3 +1,5 @@ +require 'oauth/request_proxy/action_controller_request' + module LtiHelper def lti_outcome_service?(exercise_id, external_user_id, consumer_id) return false if external_user_id == '' || consumer_id == '' diff --git a/app/models/anomaly_notification.rb b/app/models/anomaly_notification.rb index 8c9b90cd..8e9498fa 100644 --- a/app/models/anomaly_notification.rb +++ b/app/models/anomaly_notification.rb @@ -1,4 +1,4 @@ -class AnomalyNotification < ActiveRecord::Base +class AnomalyNotification < ApplicationRecord belongs_to :user, polymorphic: true belongs_to :exercise belongs_to :exercise_collection diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 00000000..10a4cba8 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/app/models/code_harbor_link.rb b/app/models/code_harbor_link.rb index 2e219aa9..338461d1 100644 --- a/app/models/code_harbor_link.rb +++ b/app/models/code_harbor_link.rb @@ -1,4 +1,4 @@ -class CodeHarborLink < ActiveRecord::Base +class CodeHarborLink < ApplicationRecord validates :oauth2token, presence: true validates :user_id, presence: true diff --git a/app/models/code_ocean/file.rb b/app/models/code_ocean/file.rb index 380f4989..a68b585b 100644 --- a/app/models/code_ocean/file.rb +++ b/app/models/code_ocean/file.rb @@ -15,7 +15,7 @@ module CodeOcean end end - class File < ActiveRecord::Base + class File < ApplicationRecord include DefaultValues DEFAULT_WEIGHT = 1.0 @@ -28,12 +28,11 @@ module CodeOcean before_validation :set_ancestor_values, if: :incomplete_descendent? belongs_to :context, polymorphic: true - belongs_to :execution_environment - belongs_to :file + belongs_to :file, class_name: 'CodeOcean::File', optional: true # This is only required for submissions and is validated below alias_method :ancestor, :file belongs_to :file_type - has_many :files + has_many :files, class_name: 'CodeOcean::File' has_many :testruns has_many :comments alias_method :descendants, :files @@ -59,6 +58,7 @@ module CodeOcean validates :role, inclusion: {in: ROLES} validates :weight, if: :teacher_defined_test?, numericality: true, presence: true validates :weight, absence: true, unless: :teacher_defined_test? + validates :file, presence: true if :context.is_a?(Submission) validates_with FileNameValidator, fields: [:name, :path, :file_type_id] diff --git a/app/models/comment.rb b/app/models/comment.rb index de2a265b..b3be54f9 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,4 @@ -class Comment < ActiveRecord::Base +class Comment < ApplicationRecord # inherit the creation module: encapsulates that this is a polymorphic user, offers some aliases and makes sure that all necessary attributes are set. include Creation attr_accessor :username, :date, :updated, :editable diff --git a/app/models/consumer.rb b/app/models/consumer.rb index 781f02b0..2dfb7c2a 100644 --- a/app/models/consumer.rb +++ b/app/models/consumer.rb @@ -1,4 +1,4 @@ -class Consumer < ActiveRecord::Base +class Consumer < ApplicationRecord has_many :users scope :with_users, -> { where('id IN (SELECT consumer_id FROM internal_users)') } diff --git a/app/models/error.rb b/app/models/error.rb index d52b3a34..623e3558 100644 --- a/app/models/error.rb +++ b/app/models/error.rb @@ -1,4 +1,4 @@ -class Error < ActiveRecord::Base +class Error < ApplicationRecord belongs_to :execution_environment scope :for_execution_environment, ->(execution_environment) { where(execution_environment_id: execution_environment.id) } diff --git a/app/models/error_template.rb b/app/models/error_template.rb index be4a3279..4265a736 100644 --- a/app/models/error_template.rb +++ b/app/models/error_template.rb @@ -1,4 +1,4 @@ -class ErrorTemplate < ActiveRecord::Base +class ErrorTemplate < ApplicationRecord belongs_to :execution_environment has_and_belongs_to_many :error_template_attributes diff --git a/app/models/error_template_attribute.rb b/app/models/error_template_attribute.rb index 844c1019..0a228958 100644 --- a/app/models/error_template_attribute.rb +++ b/app/models/error_template_attribute.rb @@ -1,4 +1,4 @@ -class ErrorTemplateAttribute < ActiveRecord::Base +class ErrorTemplateAttribute < ApplicationRecord has_and_belongs_to_many :error_template def to_s diff --git a/app/models/event.rb b/app/models/event.rb index 325fecb8..bab444df 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,7 +1,7 @@ -class Event < ActiveRecord::Base +class Event < ApplicationRecord belongs_to :user, polymorphic: true belongs_to :exercise - belongs_to :file + belongs_to :file, class_name: 'CodeOcean::File' validates :category, presence: true validates :data, presence: true diff --git a/app/models/execution_environment.rb b/app/models/execution_environment.rb index 9cd23a48..613fb082 100644 --- a/app/models/execution_environment.rb +++ b/app/models/execution_environment.rb @@ -1,6 +1,6 @@ require File.expand_path('../../../lib/active_model/validations/boolean_presence_validator', __FILE__) -class ExecutionEnvironment < ActiveRecord::Base +class ExecutionEnvironment < ApplicationRecord include Creation include DefaultValues diff --git a/app/models/exercise.rb b/app/models/exercise.rb index dbb38758..67f2a0a0 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -1,7 +1,7 @@ require 'nokogiri' require File.expand_path('../../../lib/active_model/validations/boolean_presence_validator', __FILE__) -class Exercise < ActiveRecord::Base +class Exercise < ApplicationRecord include Context include Creation include DefaultValues @@ -23,8 +23,8 @@ class Exercise < ActiveRecord::Base accepts_nested_attributes_for :exercise_tags has_many :user_exercise_feedbacks - has_many :external_users, source: :user, source_type: ExternalUser, through: :submissions - has_many :internal_users, source: :user, source_type: InternalUser, through: :submissions + has_many :external_users, source: :user, source_type: 'ExternalUser', through: :submissions + has_many :internal_users, source: :user, source_type: 'InternalUser', through: :submissions alias_method :users, :external_users scope :with_submissions, -> { where('id IN (SELECT exercise_id FROM submissions)') } diff --git a/app/models/exercise_collection.rb b/app/models/exercise_collection.rb index 80461e23..98cc5a63 100644 --- a/app/models/exercise_collection.rb +++ b/app/models/exercise_collection.rb @@ -1,4 +1,4 @@ -class ExerciseCollection < ActiveRecord::Base +class ExerciseCollection < ApplicationRecord include TimeHelper has_many :exercise_collection_items, dependent: :delete_all diff --git a/app/models/exercise_collection_item.rb b/app/models/exercise_collection_item.rb index c7b01f20..6147c3a0 100644 --- a/app/models/exercise_collection_item.rb +++ b/app/models/exercise_collection_item.rb @@ -1,4 +1,4 @@ -class ExerciseCollectionItem < ActiveRecord::Base +class ExerciseCollectionItem < ApplicationRecord belongs_to :exercise_collection belongs_to :exercise end diff --git a/app/models/exercise_tag.rb b/app/models/exercise_tag.rb index 4b8ab3e5..9ead6f13 100644 --- a/app/models/exercise_tag.rb +++ b/app/models/exercise_tag.rb @@ -1,4 +1,4 @@ -class ExerciseTag < ActiveRecord::Base +class ExerciseTag < ApplicationRecord belongs_to :tag belongs_to :exercise diff --git a/app/models/external_user.rb b/app/models/external_user.rb index b7a0ebc5..b877f08d 100644 --- a/app/models/external_user.rb +++ b/app/models/external_user.rb @@ -1,4 +1,4 @@ -class ExternalUser < ActiveRecord::Base +class ExternalUser < ApplicationRecord include User validates :consumer_id, presence: true diff --git a/app/models/file_template.rb b/app/models/file_template.rb index ef068e13..2eba68be 100644 --- a/app/models/file_template.rb +++ b/app/models/file_template.rb @@ -1,4 +1,4 @@ -class FileTemplate < ActiveRecord::Base +class FileTemplate < ApplicationRecord belongs_to :file_type diff --git a/app/models/file_type.rb b/app/models/file_type.rb index d3b519d5..ee777092 100644 --- a/app/models/file_type.rb +++ b/app/models/file_type.rb @@ -1,6 +1,6 @@ require File.expand_path('../../../lib/active_model/validations/boolean_presence_validator', __FILE__) -class FileType < ActiveRecord::Base +class FileType < ApplicationRecord include Creation include DefaultValues @@ -11,7 +11,7 @@ class FileType < ActiveRecord::Base after_initialize :set_default_values has_many :execution_environments - has_many :files + has_many :files, class_name: 'CodeOcean::File' has_many :file_templates validates :binary, boolean_presence: true diff --git a/app/models/hint.rb b/app/models/hint.rb index a14b29bc..b54ba8a2 100644 --- a/app/models/hint.rb +++ b/app/models/hint.rb @@ -1,4 +1,4 @@ -class Hint < ActiveRecord::Base +class Hint < ApplicationRecord belongs_to :execution_environment validates :execution_environment_id, presence: true diff --git a/app/models/internal_user.rb b/app/models/internal_user.rb index 8f1bf04b..e7adda6d 100644 --- a/app/models/internal_user.rb +++ b/app/models/internal_user.rb @@ -1,4 +1,4 @@ -class InternalUser < ActiveRecord::Base +class InternalUser < ApplicationRecord include User authenticates_with_sorcery! diff --git a/app/models/intervention.rb b/app/models/intervention.rb index a6693450..43750626 100644 --- a/app/models/intervention.rb +++ b/app/models/intervention.rb @@ -1,7 +1,7 @@ -class Intervention < ActiveRecord::Base +class Intervention < ApplicationRecord has_many :user_exercise_interventions - has_many :users, through: :user_exercise_interventions, source_type: "ExternalUser" + has_many :users, through: :user_exercise_interventions, source_type: 'ExternalUser' def to_s name diff --git a/app/models/lti_parameter.rb b/app/models/lti_parameter.rb index 3351a6c9..ab92165f 100644 --- a/app/models/lti_parameter.rb +++ b/app/models/lti_parameter.rb @@ -1,4 +1,4 @@ -class LtiParameter < ActiveRecord::Base +class LtiParameter < ApplicationRecord belongs_to :consumer, foreign_key: "consumers_id" belongs_to :exercise, foreign_key: "exercises_id" belongs_to :external_user, foreign_key: "external_users_id" diff --git a/app/models/proxy_exercise.rb b/app/models/proxy_exercise.rb index c6da3870..de997a0e 100644 --- a/app/models/proxy_exercise.rb +++ b/app/models/proxy_exercise.rb @@ -1,4 +1,4 @@ -class ProxyExercise < ActiveRecord::Base +class ProxyExercise < ApplicationRecord after_initialize :generate_token after_initialize :set_reason diff --git a/app/models/remote_evaluation_mapping.rb b/app/models/remote_evaluation_mapping.rb index be0034b1..8f6f6192 100644 --- a/app/models/remote_evaluation_mapping.rb +++ b/app/models/remote_evaluation_mapping.rb @@ -1,5 +1,5 @@ # todo: reference to lti_param_model -class RemoteEvaluationMapping < ActiveRecord::Base +class RemoteEvaluationMapping < ApplicationRecord before_create :generate_token, unless: :validation_token? belongs_to :exercise belongs_to :user diff --git a/app/models/request_for_comment.rb b/app/models/request_for_comment.rb index f7a425f8..fe15409b 100644 --- a/app/models/request_for_comment.rb +++ b/app/models/request_for_comment.rb @@ -1,4 +1,4 @@ -class RequestForComment < ActiveRecord::Base +class RequestForComment < ApplicationRecord include Creation belongs_to :submission belongs_to :exercise diff --git a/app/models/search.rb b/app/models/search.rb index f22dbc3e..bbb59e5b 100644 --- a/app/models/search.rb +++ b/app/models/search.rb @@ -1,4 +1,4 @@ -class Search < ActiveRecord::Base +class Search < ApplicationRecord belongs_to :user, polymorphic: true belongs_to :exercise end \ No newline at end of file diff --git a/app/models/structured_error.rb b/app/models/structured_error.rb index 851b3fb8..4d48b97c 100644 --- a/app/models/structured_error.rb +++ b/app/models/structured_error.rb @@ -1,7 +1,6 @@ -class StructuredError < ActiveRecord::Base +class StructuredError < ApplicationRecord belongs_to :error_template belongs_to :submission - belongs_to :file, class_name: 'CodeOcean::File' has_many :structured_error_attributes diff --git a/app/models/structured_error_attribute.rb b/app/models/structured_error_attribute.rb index 65bda05e..f5f7615b 100644 --- a/app/models/structured_error_attribute.rb +++ b/app/models/structured_error_attribute.rb @@ -1,4 +1,4 @@ -class StructuredErrorAttribute < ActiveRecord::Base +class StructuredErrorAttribute < ApplicationRecord belongs_to :structured_error belongs_to :error_template_attribute diff --git a/app/models/submission.rb b/app/models/submission.rb index 763e1366..13eb6ff2 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -1,4 +1,4 @@ -class Submission < ActiveRecord::Base +class Submission < ApplicationRecord include Context include Creation diff --git a/app/models/subscription.rb b/app/models/subscription.rb index abe1b513..ed3f3a3e 100644 --- a/app/models/subscription.rb +++ b/app/models/subscription.rb @@ -1,4 +1,4 @@ -class Subscription < ActiveRecord::Base +class Subscription < ApplicationRecord belongs_to :user, polymorphic: true belongs_to :request_for_comment end diff --git a/app/models/tag.rb b/app/models/tag.rb index 002ec687..b6de61bb 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -1,4 +1,4 @@ -class Tag < ActiveRecord::Base +class Tag < ApplicationRecord has_many :exercise_tags has_many :exercises, through: :exercise_tags diff --git a/app/models/testrun.rb b/app/models/testrun.rb index a266edc3..46529f98 100644 --- a/app/models/testrun.rb +++ b/app/models/testrun.rb @@ -1,4 +1,4 @@ -class Testrun < ActiveRecord::Base +class Testrun < ApplicationRecord belongs_to :file, class_name: 'CodeOcean::File' belongs_to :submission end diff --git a/app/models/user_exercise_feedback.rb b/app/models/user_exercise_feedback.rb index 3075b96e..8d7b697f 100644 --- a/app/models/user_exercise_feedback.rb +++ b/app/models/user_exercise_feedback.rb @@ -1,4 +1,4 @@ -class UserExerciseFeedback < ActiveRecord::Base +class UserExerciseFeedback < ApplicationRecord include Creation belongs_to :exercise diff --git a/app/models/user_exercise_intervention.rb b/app/models/user_exercise_intervention.rb index 60824c34..b3008206 100644 --- a/app/models/user_exercise_intervention.rb +++ b/app/models/user_exercise_intervention.rb @@ -1,4 +1,4 @@ -class UserExerciseIntervention < ActiveRecord::Base +class UserExerciseIntervention < ApplicationRecord belongs_to :user, polymorphic: true belongs_to :intervention diff --git a/app/models/user_proxy_exercise_exercise.rb b/app/models/user_proxy_exercise_exercise.rb index e7defae6..8a0cbb5d 100644 --- a/app/models/user_proxy_exercise_exercise.rb +++ b/app/models/user_proxy_exercise_exercise.rb @@ -1,4 +1,4 @@ -class UserProxyExerciseExercise < ActiveRecord::Base +class UserProxyExerciseExercise < ApplicationRecord belongs_to :user, polymorphic: true belongs_to :exercise diff --git a/app/views/admin/dashboard/show.html.slim b/app/views/admin/dashboard/show.html.slim index c09c7f82..5771b44f 100644 --- a/app/views/admin/dashboard/show.html.slim +++ b/app/views/admin/dashboard/show.html.slim @@ -1,7 +1,3 @@ -- content_for :head do - = javascript_include_tag(asset_path('vis.min.js', type: :javascript)) - = stylesheet_link_tag(asset_path('vis.min.css', type: :stylesheet)) - h1 = t('breadcrumbs.dashboard.show') h2 Version diff --git a/app/views/application/_locale_selector.html.slim b/app/views/application/_locale_selector.html.slim index 28f4626c..b6dbbfbf 100644 --- a/app/views/application/_locale_selector.html.slim +++ b/app/views/application/_locale_selector.html.slim @@ -4,4 +4,4 @@ li.dropdown span.caret ul.dropdown-menu role='menu' - I18n.available_locales.sort_by { |locale| t("locales.#{locale}") }.each do |locale| - li = link_to(t("locales.#{locale}"), url_for(params.merge(locale: locale))) + li = link_to(t("locales.#{locale}"), url_for(params.permit!.merge(locale: locale))) diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index 915d1832..2329e93d 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -5,12 +5,8 @@ html lang='en' meta name='viewport' content='width=device-width, initial-scale=1' title = application_name link href=asset_path('favicon.png') rel='icon' type='image/png' - = stylesheet_link_tag(asset_path('bootstrap.min.css', type: :stylesheet)) - = stylesheet_link_tag(asset_path('font-awesome.min.css', type: :stylesheet)) = stylesheet_link_tag('application', media: 'all', 'data-turbolinks-track' => true) = javascript_include_tag('application', 'data-turbolinks-track' => true) - = javascript_include_tag(asset_path('underscore-min.js', type: :javascript)) - = javascript_include_tag(asset_path('bootstrap.min.js', type: :javascript)) = yield(:head) = csrf_meta_tags body diff --git a/app/views/statistics/activity_history.html.slim b/app/views/statistics/activity_history.html.slim index b8efa71e..afdd7070 100644 --- a/app/views/statistics/activity_history.html.slim +++ b/app/views/statistics/activity_history.html.slim @@ -1,7 +1,3 @@ -- content_for :head do - = javascript_include_tag(asset_path('vis.min.js', type: :javascript)) - = stylesheet_link_tag(asset_path('vis.min.css', type: :stylesheet)) - .group .title h1 = t("statistics.graphs.#{resource}_activity") diff --git a/app/views/statistics/graphs.html.slim b/app/views/statistics/graphs.html.slim index 75baf168..9d23245b 100644 --- a/app/views/statistics/graphs.html.slim +++ b/app/views/statistics/graphs.html.slim @@ -1,7 +1,3 @@ -- content_for :head do - = javascript_include_tag(asset_path('vis.min.js', type: :javascript)) - = stylesheet_link_tag(asset_path('vis.min.css', type: :stylesheet)) - .group .title h1 = t('.user_activity') diff --git a/bin/bundle b/bin/bundle index 66e9889e..f19acf5b 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,3 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails index 5191e692..07396602 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/setup b/bin/setup index acdb2c13..94fd4d79 100755 --- a/bin/setup +++ b/bin/setup @@ -1,29 +1,36 @@ #!/usr/bin/env ruby -require 'pathname' +require 'fileutils' +include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = File.expand_path('..', __dir__) -Dir.chdir APP_ROOT do +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do # This script is a starting point to setup your application. - # Add necessary setup steps to this file: + # Add necessary setup steps to this file. - puts "== Installing dependencies ==" - system "gem install bundler --conservative" - system "bundle check || bundle install" + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # system "cp config/database.yml.sample config/database.yml" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system "bin/rake db:setup" + system! 'bin/rails db:setup' puts "\n== Removing old logs and tempfiles ==" - system "rm -f log/*" - system "rm -rf tmp/cache" + system! 'bin/rails log:clear tmp:clear' puts "\n== Restarting application server ==" - system "touch tmp/restart.txt" + system! 'bin/rails restart' end diff --git a/bin/update b/bin/update new file mode 100755 index 00000000..58bfaed5 --- /dev/null +++ b/bin/update @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/yarn b/bin/yarn new file mode 100755 index 00000000..460dd565 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + begin + exec "yarnpkg", *ARGV + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/config/application.rb b/config/application.rb index 97118237..49bae23f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,4 @@ -require File.expand_path('../boot', __FILE__) +require_relative 'boot' require 'rails/all' @@ -8,9 +8,13 @@ Bundler.require(*Rails.groups) module CodeOcean class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.0 + # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. + # Application configuration can go into files in config/initializers + # -- all .rb files in that directory are automatically loaded after loading + # the framework and any gems in your application. # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. @@ -21,23 +25,8 @@ module CodeOcean # config.i18n.default_locale = :de config.i18n.available_locales = [:de, :en] - # Do not swallow errors in after_commit/after_rollback callbacks. - config.active_record.raise_in_transactional_callbacks = true - config.autoload_paths << Rails.root.join('lib') config.eager_load_paths << Rails.root.join('lib') config.assets.precompile += %w( markdown-buttons.png ) - - #config.active_record.schema_format = :sql - - case (RUBY_ENGINE) - when 'ruby' - # ... - #this is enabled in prod for testing - config.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement - when 'jruby' - # plattform specific - java.lang.Class.for_name('javax.crypto.JceSecurity').get_declared_field('isRestricted').tap{|f| f.accessible = true; f.set nil, false} - end end end diff --git a/config/boot.rb b/config/boot.rb index 6b750f00..4423c97f 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,4 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. +# require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 00000000..1060cbe2 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: code_ocean_production diff --git a/config/code_ocean.yml.example b/config/code_ocean.yml.example index e8cb10d0..30cd4639 100644 --- a/config/code_ocean.yml.example +++ b/config/code_ocean.yml.example @@ -6,7 +6,7 @@ default: &default development: flowr: - enabled: true + enabled: false url: http://example.org:3000/api/exceptioninfo?id=&lang=auto code_pilot: enabled: false diff --git a/config/environment.rb b/config/environment.rb index ee8d90dc..d4654f20 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,8 @@ # Load the Rails application. -require File.expand_path('../application', __FILE__) +require_relative 'application' + +# LTI 1.x uses OAuth 1.0 +OAUTH_10_SUPPORT = true # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 7fcbb05d..7bd31651 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -11,21 +11,41 @@ Rails.application.configure do # Do not eager load code on boot. config.eager_load = false - # Show full error reports and disable caching. - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - - config.action_mailer.perform_deliveries = false + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false + config.action_mailer.perform_caching = false + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. @@ -48,6 +68,7 @@ Rails.application.configure do BetterErrors::Middleware.allow_ip! ENV['TRUSTED_IP'] if ENV['TRUSTED_IP'] - # Delete middleware in order to allow concurrent requests. - config.middleware.delete(Rack::Lock) + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker end diff --git a/config/environments/production.rb b/config/environments/production.rb index 23c4e5b4..6658bc87 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -14,15 +14,13 @@ Rails.application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Enable Rack::Cache to put a simple HTTP cache in front of your application - # Add `rack-cache` to your Gemfile before enabling this. - # For large-scale production use, consider using a caching reverse proxy like - # NGINX, varnish or squid. - # config.action_dispatch.rack_cache = true + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier @@ -37,10 +35,21 @@ Rails.application.configure do # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true @@ -49,16 +58,16 @@ Rails.application.configure do config.log_level = :error # Prepend all log lines with the following tags. - # config.log_tags = [ :subdomain, :uuid ] - - # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # config.log_tags = [ :subdomain, :uuid, :request_id ] # Use a different cache store in production. # config.cache_store = :mem_cache_store - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "code_ocean_#{Rails.env}" + + config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. @@ -74,6 +83,16 @@ Rails.application.configure do # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false end diff --git a/config/environments/test.rb b/config/environments/test.rb index a5c78bf9..5d112d40 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -12,9 +12,11 @@ Rails.application.configure do # preloads Rails for running tests, you may have to set it to true. config.eager_load = false - # Configure static file server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } # Show full error reports and disable caching. config.consider_all_requests_local = true @@ -26,6 +28,11 @@ Rails.application.configure do # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 00000000..89d2efab --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d74f7733..592a9bbd 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,12 +1,17 @@ # Be sure to restart your server when you modify this file. -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' +Rails.application.config.tap do |config| -# Add additional assets to the asset load path -# Rails.application.config.assets.paths << Emoji.images_path + # Version of your assets, change this if you want to expire all your assets. + config.assets.version = '1.0' -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) -Rails.application.config.assets.precompile += %w( markdown-buttons.png ) \ No newline at end of file + # Add additional assets to the asset load path. + # config.assets.paths << Emoji.images_path + # Add Yarn node_modules folder to the asset load path. + # config.assets.paths << Rails.root.join('node_modules') + + # Precompile additional assets. + # application.js, application.css, and all non-JS/CSS in the app/assets + # folder are already added. + # config.assets.precompile += %w( admin.js admin.css ) +end diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 00000000..d3bcaa5e --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 7f70458d..5a6a32d3 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ # Be sure to restart your server when you modify this file. +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/docker.rb b/config/initializers/docker.rb index 809707fb..ce43654b 100644 --- a/config/initializers/docker.rb +++ b/config/initializers/docker.rb @@ -1,6 +1,6 @@ DockerClient.initialize_environment unless Rails.env.test? && `which docker`.blank? -if ActiveRecord::Base.connection.tables.present? && DockerContainerPool.config[:active] +if ApplicationRecord.connection.tables.present? && DockerContainerPool.config[:active] DockerContainerPool.start_refill_task at_exit { DockerContainerPool.clean_up } end diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb new file mode 100644 index 00000000..a2bfed30 --- /dev/null +++ b/config/initializers/new_framework_defaults.rb @@ -0,0 +1,20 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.0 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Enable per-form CSRF tokens. Previous versions had false. +Rails.application.config.action_controller.per_form_csrf_tokens = false + +# Enable origin-checking CSRF mitigation. Previous versions had false. +Rails.application.config.action_controller.forgery_protection_origin_check = false + +# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. +# Previous versions had false. +ActiveSupport.to_time_preserves_timezone = false + +# Require `belongs_to` associations by default. Previous versions had false. +Rails.application.config.active_record.belongs_to_required_by_default = false diff --git a/config/initializers/new_framework_defaults_5_1.rb b/config/initializers/new_framework_defaults_5_1.rb new file mode 100644 index 00000000..9010abd5 --- /dev/null +++ b/config/initializers/new_framework_defaults_5_1.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.1 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make `form_with` generate non-remote forms. +Rails.application.config.action_view.form_with_generates_remote_forms = false + +# Unknown asset fallback will return the path passed in when the given +# asset is not present in the asset pipeline. +# Rails.application.config.assets.unknown_asset_fallback = false diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb new file mode 100644 index 00000000..c383d072 --- /dev/null +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -0,0 +1,38 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.2 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make Active Record use stable #cache_key alongside new #cache_version method. +# This is needed for recyclable cache keys. +# Rails.application.config.active_record.cache_versioning = true + +# Use AES-256-GCM authenticated encryption for encrypted cookies. +# Also, embed cookie expiry in signed or encrypted cookies for increased security. +# +# This option is not backwards compatible with earlier Rails versions. +# It's best enabled when your entire app is migrated and stable on 5.2. +# +# Existing cookies will be converted on read then written with the new scheme. +# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true + +# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages +# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. +# Rails.application.config.active_support.use_authenticated_message_encryption = true + +# Add default protection from forgery to ActionController::Base instead of in +# ApplicationController. +# Rails.application.config.action_controller.default_protect_from_forgery = true + +# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and +# 'f' after migrating old data. +# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true + +# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. +# Rails.application.config.active_support.use_sha1_digests = true + +# Make `form_with` generate id attributes for any generated HTML tags. +# Rails.application.config.action_view.form_with_generates_ids = true diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 33725e95..bbfc3961 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -5,10 +5,10 @@ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. ActiveSupport.on_load(:action_controller) do - wrap_parameters format: [:json] if respond_to?(:wrap_parameters) + wrap_parameters format: [:json] end # To enable root element in JSON for ActiveRecord objects. # ActiveSupport.on_load(:active_record) do -# self.include_root_in_json = true +# self.include_root_in_json = true # end diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 00000000..a5eccf81 --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,34 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/secrets.yml.example b/config/secrets.yml.example index bc69f9d6..656e1048 100644 --- a/config/secrets.yml.example +++ b/config/secrets.yml.example @@ -5,18 +5,28 @@ # Make sure the secret is at least 30 characters and all random, # no regular words or you'll be exposed to dictionary attacks. -# You can use `rake secret` to generate a secure secret key. +# You can use `rails secret` to generate a secure secret key. # Make sure the secrets in this file are kept private # if you're sharing your code publicly. +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + development: secret_key_base: CHANGE_ME test: secret_key_base: CHANGE_ME -# Do not keep production secrets in the repository, -# instead read values from the environment. +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + production: secret_key_base: CHANGE_ME diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 00000000..c9119b40 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 00000000..d32f76e8 --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/db/migrate/20170112151637_create_lti_parameters.rb b/db/migrate/20170112151637_create_lti_parameters.rb index c7613edf..80348843 100644 --- a/db/migrate/20170112151637_create_lti_parameters.rb +++ b/db/migrate/20170112151637_create_lti_parameters.rb @@ -4,7 +4,7 @@ class CreateLtiParameters < ActiveRecord::Migration t.belongs_to :external_users t.belongs_to :consumers t.belongs_to :exercises - t.jsonb :lti_parameters, null: false, default: '{}' + t.jsonb :lti_parameters, null: false, default: {} t.timestamps end end diff --git a/db/seeds.rb b/db/seeds.rb index 28d543ef..dab9ab7d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -18,7 +18,7 @@ end # delete all present records Rails.application.eager_load! -(ActiveRecord::Base.descendants - [ActiveRecord::SchemaMigration]).each(&:delete_all) +(ApplicationRecord.descendants - [ActiveRecord::SchemaMigration]).each(&:delete_all) # delete file uploads FileUtils.rm_rf(Rails.root.join('public', 'uploads')) diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 55c458ca..b19a9dc2 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -272,7 +272,7 @@ class DockerClient end #ensure # guarantee that the thread is releasing the DB connection after it is done - # ActiveRecord::Base.connectionpool.releaseconnection + # ApplicationRecord.connectionpool.releaseconnection #end end end diff --git a/provision.sh b/provision.sh index 43d72c90..324a2b25 100644 --- a/provision.sh +++ b/provision.sh @@ -5,8 +5,8 @@ ######## VERSION INFORMATION ######## postgres_version=10 -ruby_version=2.3.6 -rails_version=4.2.10 +ruby_version=2.5.1 +rails_version=5.2.1 ########## INSTALL SCRIPT ########### diff --git a/spec/concerns/lti_spec.rb b/spec/concerns/lti_spec.rb index 4fb8dc5f..bdc5901e 100644 --- a/spec/concerns/lti_spec.rb +++ b/spec/concerns/lti_spec.rb @@ -153,7 +153,7 @@ describe Lti do end describe '#store_lti_session_data' do - let(:parameters) { {} } + let(:parameters) { ActionController::Parameters.new({}) } it 'stores data in the session' do controller.instance_variable_set(:@current_user, FactoryBot.create(:external_user)) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index eec0abbe..e8fdfcf9 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -40,14 +40,14 @@ describe ApplicationController do context "using the 'custom_locale' parameter" do it 'overwrites the session' do expect(session).to receive(:[]=).with(:locale, locale.to_s) - get :welcome, custom_locale: locale + get :welcome, params: { custom_locale: locale } end end context "using the 'locale' parameter" do it 'overwrites the session' do expect(session).to receive(:[]=).with(:locale, locale.to_s) - get :welcome, locale: locale + get :welcome, params: { locale: locale } end end end diff --git a/spec/controllers/code_ocean/files_controller_spec.rb b/spec/controllers/code_ocean/files_controller_spec.rb index 9bed884b..16234a66 100644 --- a/spec/controllers/code_ocean/files_controller_spec.rb +++ b/spec/controllers/code_ocean/files_controller_spec.rb @@ -8,7 +8,7 @@ describe CodeOcean::FilesController do let(:submission) { FactoryBot.create(:submission, user: user) } context 'with a valid file' do - let(:request) { proc { post :create, code_ocean_file: FactoryBot.build(:file, context: submission).attributes, format: :json } } + let(:request) { proc { post :create, params: { code_ocean_file: FactoryBot.build(:file, context: submission).attributes, format: :json } } } before(:each) { request.call } expect_assigns(file: CodeOcean::File) @@ -22,7 +22,7 @@ describe CodeOcean::FilesController do end context 'with an invalid file' do - before(:each) { post :create, code_ocean_file: {context_id: submission.id, context_type: Submission}, format: :json } + before(:each) { post :create, params: { code_ocean_file: {context_id: submission.id, context_type: Submission}, format: :json } } expect_assigns(file: CodeOcean::File) expect_json @@ -32,7 +32,7 @@ describe CodeOcean::FilesController do describe 'DELETE #destroy' do let(:exercise) { FactoryBot.create(:fibonacci) } - let(:request) { proc { delete :destroy, id: exercise.files.first.id } } + let(:request) { proc { delete :destroy, params: { id: exercise.files.first.id } } } before(:each) { request.call } expect_assigns(file: CodeOcean::File) diff --git a/spec/controllers/consumers_controller_spec.rb b/spec/controllers/consumers_controller_spec.rb index 448f13dc..5eda1e93 100644 --- a/spec/controllers/consumers_controller_spec.rb +++ b/spec/controllers/consumers_controller_spec.rb @@ -7,7 +7,7 @@ describe ConsumersController do describe 'POST #create' do context 'with a valid consumer' do - let(:request) { proc { post :create, consumer: FactoryBot.attributes_for(:consumer) } } + let(:request) { proc { post :create, params: { consumer: FactoryBot.attributes_for(:consumer) } } } before(:each) { request.call } expect_assigns(consumer: Consumer) @@ -20,7 +20,7 @@ describe ConsumersController do end context 'with an invalid consumer' do - before(:each) { post :create, consumer: {} } + before(:each) { post :create, params: { consumer: {} } } expect_assigns(consumer: Consumer) expect_status(200) @@ -29,20 +29,20 @@ describe ConsumersController do end describe 'DELETE #destroy' do - before(:each) { delete :destroy, id: consumer.id } + before(:each) { delete :destroy, params: { id: consumer.id } } expect_assigns(consumer: Consumer) it 'destroys the consumer' do consumer = FactoryBot.create(:consumer) - expect { delete :destroy, id: consumer.id }.to change(Consumer, :count).by(-1) + expect { delete :destroy, params: { id: consumer.id } }.to change(Consumer, :count).by(-1) end expect_redirect(:consumers) end describe 'GET #edit' do - before(:each) { get :edit, id: consumer.id } + before(:each) { get :edit, params: { id: consumer.id } } expect_assigns(consumer: Consumer) expect_status(200) @@ -67,7 +67,7 @@ describe ConsumersController do end describe 'GET #show' do - before(:each) { get :show, id: consumer.id } + before(:each) { get :show, params: { id: consumer.id } } expect_assigns(consumer: :consumer) expect_status(200) @@ -76,14 +76,14 @@ describe ConsumersController do describe 'PUT #update' do context 'with a valid consumer' do - before(:each) { put :update, consumer: FactoryBot.attributes_for(:consumer), id: consumer.id } + before(:each) { put :update, params: { consumer: FactoryBot.attributes_for(:consumer), id: consumer.id } } expect_assigns(consumer: Consumer) expect_redirect(:consumer) end context 'with an invalid consumer' do - before(:each) { put :update, consumer: {name: ''}, id: consumer.id } + before(:each) { put :update, params: { consumer: {name: ''}, id: consumer.id } } expect_assigns(consumer: Consumer) expect_status(200) diff --git a/spec/controllers/error_template_attributes_controller_spec.rb b/spec/controllers/error_template_attributes_controller_spec.rb index 27e33247..d1cb3d4f 100644 --- a/spec/controllers/error_template_attributes_controller_spec.rb +++ b/spec/controllers/error_template_attributes_controller_spec.rb @@ -17,27 +17,27 @@ describe ErrorTemplateAttributesController do end it "should create error_template_attribute" do - expect { post :create, error_template_attribute: { } }.to change(ErrorTemplateAttribute, :count).by(1) + expect { post :create, params: { error_template_attribute: { } } }.to change(ErrorTemplateAttribute, :count).by(1) expect(response).to redirect_to(error_template_attribute_path(assigns(:error_template_attribute))) end it "should show error_template_attribute" do - get :show, id: error_template_attribute + get :show, params: { id: error_template_attribute } expect(response.status).to eq(200) end it "should get edit" do - get :edit, id: error_template_attribute + get :edit, params: { id: error_template_attribute } expect(response.status).to eq(200) end it "should update error_template_attribute" do - patch :update, id: error_template_attribute, error_template_attribute: { } + patch :update, params: { id: error_template_attribute, error_template_attribute: FactoryBot.attributes_for(:error_template_attribute) } expect(response).to redirect_to(error_template_attribute_path(assigns(:error_template_attribute))) end it "should destroy error_template_attribute" do - expect { delete :destroy, id: error_template_attribute }.to change(ErrorTemplateAttribute, :count).by(-1) + expect { delete :destroy, params: { id: error_template_attribute } }.to change(ErrorTemplateAttribute, :count).by(-1) expect(response).to redirect_to(error_template_attributes_path) end end diff --git a/spec/controllers/error_templates_controller_spec.rb b/spec/controllers/error_templates_controller_spec.rb index abff452f..9f5da525 100644 --- a/spec/controllers/error_templates_controller_spec.rb +++ b/spec/controllers/error_templates_controller_spec.rb @@ -17,27 +17,27 @@ describe ErrorTemplatesController do end it "should create error_template" do - expect { post :create, error_template: { } }.to change(ErrorTemplate, :count).by(1) + expect { post :create, params: {error_template: { execution_environment_id: error_template.execution_environment.id } } }.to change(ErrorTemplate, :count).by(1) expect(response).to redirect_to(error_template_path(assigns(:error_template))) end it "should show error_template" do - get :show, id: error_template + get :show, params: { id: error_template } expect(response.status).to eq(200) end it "should get edit" do - get :edit, id: error_template + get :edit, params: { id: error_template } expect(response.status).to eq(200) end it "should update error_template" do - patch :update, id: error_template, error_template: { } + patch :update, params: { id: error_template, error_template: FactoryBot.attributes_for(:error_template) } expect(response).to redirect_to(error_template_path(assigns(:error_template))) end it "should destroy error_template" do - expect { delete :destroy, id: error_template }.to change(ErrorTemplate, :count).by(-1) + expect { delete :destroy, params: { id: error_template } }.to change(ErrorTemplate, :count).by(-1) expect(response).to redirect_to(error_templates_path) end end diff --git a/spec/controllers/events_controller_spec.rb b/spec/controllers/events_controller_spec.rb index bd9e11a8..ecfc611c 100644 --- a/spec/controllers/events_controller_spec.rb +++ b/spec/controllers/events_controller_spec.rb @@ -7,7 +7,7 @@ describe EventsController do describe 'POST #create' do context 'with a valid event' do - let(:request) { proc { post :create, event: {category: 'foo', data: 'bar', exercise_id: exercise.id, file_id: exercise.files[0].id} } } + let(:request) { proc { post :create, params: { event: {category: 'foo', data: 'bar', exercise_id: exercise.id, file_id: exercise.files[0].id} } } } before(:each) { request.call } expect_assigns(event: Event) @@ -20,7 +20,7 @@ describe EventsController do end context 'with an invalid event' do - before(:each) { post :create, event: {exercise_id: 847482} } + before(:each) { post :create, params: { event: {exercise_id: 847482} } } expect_assigns(event: Event) expect_status(422) end diff --git a/spec/controllers/execution_environments_controller_spec.rb b/spec/controllers/execution_environments_controller_spec.rb index ee9ba3d5..6e8bf4c4 100644 --- a/spec/controllers/execution_environments_controller_spec.rb +++ b/spec/controllers/execution_environments_controller_spec.rb @@ -9,7 +9,7 @@ describe ExecutionEnvironmentsController do before(:each) { expect(DockerClient).to receive(:image_tags).at_least(:once).and_return([]) } context 'with a valid execution environment' do - let(:request) { proc { post :create, execution_environment: FactoryBot.attributes_for(:ruby) } } + let(:request) { proc { post :create, params: { execution_environment: FactoryBot.build(:ruby).attributes } } } before(:each) { request.call } expect_assigns(docker_images: Array) @@ -23,7 +23,7 @@ describe ExecutionEnvironmentsController do end context 'with an invalid execution environment' do - before(:each) { post :create, execution_environment: {} } + before(:each) { post :create, params: { execution_environment: {} } } expect_assigns(execution_environment: ExecutionEnvironment) expect_status(200) @@ -32,13 +32,13 @@ describe ExecutionEnvironmentsController do end describe 'DELETE #destroy' do - before(:each) { delete :destroy, id: execution_environment.id } + before(:each) { delete :destroy, params: { id: execution_environment.id } } expect_assigns(execution_environment: :execution_environment) it 'destroys the execution environment' do execution_environment = FactoryBot.create(:ruby) - expect { delete :destroy, id: execution_environment.id }.to change(ExecutionEnvironment, :count).by(-1) + expect { delete :destroy, params: { id: execution_environment.id } }.to change(ExecutionEnvironment, :count).by(-1) end expect_redirect(:execution_environments) @@ -47,7 +47,7 @@ describe ExecutionEnvironmentsController do describe 'GET #edit' do before(:each) do expect(DockerClient).to receive(:image_tags).at_least(:once).and_return([]) - get :edit, id: execution_environment.id + get :edit, params: { id: execution_environment.id } end expect_assigns(docker_images: Array) @@ -62,7 +62,7 @@ describe ExecutionEnvironmentsController do before(:each) do expect(DockerClient).to receive(:new).with(execution_environment: execution_environment).and_call_original expect_any_instance_of(DockerClient).to receive(:execute_arbitrary_command).with(command) - post :execute_command, command: command, id: execution_environment.id + post :execute_command, params: { command: command, id: execution_environment.id } end expect_assigns(docker_client: DockerClient) @@ -123,7 +123,7 @@ describe ExecutionEnvironmentsController do end describe 'GET #shell' do - before(:each) { get :shell, id: execution_environment.id } + before(:each) { get :shell, params: { id: execution_environment.id } } expect_assigns(execution_environment: :execution_environment) expect_status(200) @@ -131,7 +131,7 @@ describe ExecutionEnvironmentsController do end describe 'GET #statistics' do - before(:each) { get :statistics, id: execution_environment.id } + before(:each) { get :statistics, params: { id: execution_environment.id } } expect_assigns(execution_environment: :execution_environment) expect_status(200) @@ -139,7 +139,7 @@ describe ExecutionEnvironmentsController do end describe 'GET #show' do - before(:each) { get :show, id: execution_environment.id } + before(:each) { get :show, params: { id: execution_environment.id } } expect_assigns(execution_environment: :execution_environment) expect_status(200) @@ -150,7 +150,7 @@ describe ExecutionEnvironmentsController do context 'with a valid execution environment' do before(:each) do expect(DockerClient).to receive(:image_tags).at_least(:once).and_return([]) - put :update, execution_environment: FactoryBot.attributes_for(:ruby), id: execution_environment.id + put :update, params: { execution_environment: FactoryBot.attributes_for(:ruby), id: execution_environment.id } end expect_assigns(docker_images: Array) @@ -159,7 +159,7 @@ describe ExecutionEnvironmentsController do end context 'with an invalid execution environment' do - before(:each) { put :update, execution_environment: {name: ''}, id: execution_environment.id } + before(:each) { put :update, params: { execution_environment: {name: ''}, id: execution_environment.id } } expect_assigns(execution_environment: ExecutionEnvironment) expect_status(200) diff --git a/spec/controllers/exercises_controller_spec.rb b/spec/controllers/exercises_controller_spec.rb index f1d5db96..3144280a 100644 --- a/spec/controllers/exercises_controller_spec.rb +++ b/spec/controllers/exercises_controller_spec.rb @@ -6,8 +6,8 @@ describe ExercisesController do before(:each) { allow(controller).to receive(:current_user).and_return(user) } describe 'PUT #batch_update' do - let(:attributes) { {public: true} } - let(:request) { proc { put :batch_update, exercises: {0 => attributes.merge(id: exercise.id)} } } + let(:attributes) { { 'public': 'true'} } + let(:request) { proc { put :batch_update, params: { exercises: {0 => attributes.merge(id: exercise.id)} } } } before(:each) { request.call } it 'updates the exercises' do @@ -20,7 +20,7 @@ describe ExercisesController do end describe 'POST #clone' do - let(:request) { proc { post :clone, id: exercise.id } } + let(:request) { proc { post :clone, params: { id: exercise.id } } } context 'when saving succeeds' do before(:each) { request.call } @@ -55,7 +55,7 @@ describe ExercisesController do let(:exercise_attributes) { FactoryBot.build(:dummy).attributes } context 'with a valid exercise' do - let(:request) { proc { post :create, exercise: exercise_attributes } } + let(:request) { proc { post :create, params: { exercise: exercise_attributes } } } before(:each) { request.call } expect_assigns(exercise: Exercise) @@ -68,7 +68,7 @@ describe ExercisesController do end context 'when including a file' do - let(:request) { proc { post :create, exercise: exercise_attributes.merge(files_attributes: files_attributes) } } + let(:request) { proc { post :create, params: { exercise: exercise_attributes.merge(files_attributes: files_attributes) } } } context 'when specifying the file content within the form' do let(:files_attributes) { {'0' => FactoryBot.build(:file).attributes} } @@ -114,7 +114,7 @@ describe ExercisesController do end context 'with an invalid exercise' do - before(:each) { post :create, exercise: {} } + before(:each) { post :create, params: { exercise: { } } } expect_assigns(exercise: Exercise) expect_status(200) @@ -123,20 +123,20 @@ describe ExercisesController do end describe 'DELETE #destroy' do - before(:each) { delete :destroy, id: exercise.id } + before(:each) { delete :destroy, params: { id: exercise.id } } expect_assigns(exercise: :exercise) it 'destroys the exercise' do exercise = FactoryBot.create(:dummy) - expect { delete :destroy, id: exercise.id }.to change(Exercise, :count).by(-1) + expect { delete :destroy, params: { id: exercise.id } }.to change(Exercise, :count).by(-1) end expect_redirect(:exercises) end describe 'GET #edit' do - before(:each) { get :edit, id: exercise.id } + before(:each) { get :edit, params: { id: exercise.id } } expect_assigns(exercise: :exercise) expect_status(200) @@ -144,7 +144,7 @@ describe ExercisesController do end describe 'GET #implement' do - let(:request) { proc { get :implement, id: exercise.id } } + let(:request) { proc { get :implement, params: { id: exercise.id } } } context 'with an exercise with visible files' do let(:exercise) { FactoryBot.create(:fibonacci) } @@ -201,7 +201,7 @@ describe ExercisesController do describe 'GET #show' do context 'as admin' do - before(:each) { get :show, id: exercise.id } + before(:each) { get :show, params: { id: exercise.id } } expect_assigns(exercise: :exercise) expect_status(200) @@ -211,7 +211,7 @@ describe ExercisesController do describe 'GET #reload' do context 'as anyone' do - before(:each) { get :reload, format: :json, id: exercise.id } + before(:each) { get :reload, format: :json, params: { id: exercise.id } } expect_assigns(exercise: :exercise) expect_status(200) @@ -220,7 +220,7 @@ describe ExercisesController do end describe 'GET #statistics' do - before(:each) { get :statistics, id: exercise.id } + before(:each) { get :statistics, params: { id: exercise.id } } expect_assigns(exercise: :exercise) expect_status(200) @@ -229,7 +229,7 @@ describe ExercisesController do describe 'POST #submit' do let(:output) { {} } - let(:request) { post :submit, format: :json, id: exercise.id, submission: {cause: 'submit', exercise_id: exercise.id} } + let(:request) { post :submit, format: :json, params: { id: exercise.id, submission: {cause: 'submit', exercise_id: exercise.id} } } let!(:external_user) { FactoryBot.create(:external_user) } let!(:lti_parameter) { FactoryBot.create(:lti_parameter, external_user: external_user, exercise: exercise) } @@ -299,14 +299,14 @@ describe ExercisesController do describe 'PUT #update' do context 'with a valid exercise' do let(:exercise_attributes) { FactoryBot.build(:dummy).attributes } - before(:each) { put :update, exercise: exercise_attributes, id: exercise.id } + before(:each) { put :update, params: { exercise: exercise_attributes, id: exercise.id } } expect_assigns(exercise: Exercise) expect_redirect(:exercise) end context 'with an invalid exercise' do - before(:each) { put :update, exercise: {title: ''}, id: exercise.id } + before(:each) { put :update, params: { exercise: {title: ''}, id: exercise.id } } expect_assigns(exercise: Exercise) expect_status(200) diff --git a/spec/controllers/external_users_controller_spec.rb b/spec/controllers/external_users_controller_spec.rb index c8df8da7..20699899 100644 --- a/spec/controllers/external_users_controller_spec.rb +++ b/spec/controllers/external_users_controller_spec.rb @@ -14,7 +14,7 @@ describe ExternalUsersController do end describe 'GET #show' do - before(:each) { get :show, id: users.first.id } + before(:each) { get :show, params: { id: users.first.id } } expect_assigns(user: ExternalUser) expect_status(200) diff --git a/spec/controllers/file_types_controller_spec.rb b/spec/controllers/file_types_controller_spec.rb index 83e8396b..77a7e372 100644 --- a/spec/controllers/file_types_controller_spec.rb +++ b/spec/controllers/file_types_controller_spec.rb @@ -7,7 +7,7 @@ describe FileTypesController do describe 'POST #create' do context 'with a valid file type' do - let(:request) { proc { post :create, file_type: FactoryBot.attributes_for(:dot_rb) } } + let(:request) { proc { post :create, params: { file_type: FactoryBot.attributes_for(:dot_rb) } } } before(:each) { request.call } expect_assigns(editor_modes: Array) @@ -21,7 +21,7 @@ describe FileTypesController do end context 'with an invalid file type' do - before(:each) { post :create, file_type: {} } + before(:each) { post :create, params: { file_type: { } } } expect_assigns(editor_modes: Array) expect_assigns(file_type: FileType) @@ -31,20 +31,20 @@ describe FileTypesController do end describe 'DELETE #destroy' do - before(:each) { delete :destroy, id: file_type.id } + before(:each) { delete :destroy, params: { id: file_type.id } } expect_assigns(file_type: FileType) it 'destroys the file type' do file_type = FactoryBot.create(:dot_rb) - expect { delete :destroy, id: file_type.id }.to change(FileType, :count).by(-1) + expect { delete :destroy, params: { id: file_type.id } }.to change(FileType, :count).by(-1) end expect_redirect(:file_types) end describe 'GET #edit' do - before(:each) { get :edit, id: file_type.id } + before(:each) { get :edit, params: { id: file_type.id } } expect_assigns(editor_modes: Array) expect_assigns(file_type: FileType) @@ -71,7 +71,7 @@ describe FileTypesController do end describe 'GET #show' do - before(:each) { get :show, id: file_type.id } + before(:each) { get :show, params: { id: file_type.id } } expect_assigns(file_type: :file_type) expect_status(200) @@ -80,7 +80,7 @@ describe FileTypesController do describe 'PUT #update' do context 'with a valid file type' do - before(:each) { put :update, file_type: FactoryBot.attributes_for(:dot_rb), id: file_type.id } + before(:each) { put :update, params: { file_type: FactoryBot.attributes_for(:dot_rb), id: file_type.id } } expect_assigns(editor_modes: Array) expect_assigns(file_type: FileType) @@ -88,7 +88,7 @@ describe FileTypesController do end context 'with an invalid file type' do - before(:each) { put :update, file_type: {name: ''}, id: file_type.id } + before(:each) { put :update, params: { file_type: {name: ''}, id: file_type.id } } expect_assigns(editor_modes: Array) expect_assigns(file_type: FileType) diff --git a/spec/controllers/hints_controller_spec.rb b/spec/controllers/hints_controller_spec.rb index f54d09ad..dcd62d7b 100644 --- a/spec/controllers/hints_controller_spec.rb +++ b/spec/controllers/hints_controller_spec.rb @@ -8,7 +8,7 @@ describe HintsController do describe 'POST #create' do context 'with a valid hint' do - let(:request) { proc { post :create, execution_environment_id: execution_environment.id, hint: FactoryBot.attributes_for(:ruby_syntax_error) } } + let(:request) { proc { post :create, params: { execution_environment_id: execution_environment.id, hint: FactoryBot.attributes_for(:ruby_syntax_error) } } } before(:each) { request.call } expect_assigns(execution_environment: :execution_environment) @@ -22,7 +22,7 @@ describe HintsController do end context 'with an invalid hint' do - before(:each) { post :create, execution_environment_id: execution_environment.id, hint: {} } + before(:each) { post :create, params: { execution_environment_id: execution_environment.id, hint: {} } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: Hint) @@ -32,21 +32,21 @@ describe HintsController do end describe 'DELETE #destroy' do - before(:each) { delete :destroy, execution_environment_id: execution_environment.id, id: hint.id } + before(:each) { delete :destroy, params: { execution_environment_id: execution_environment.id, id: hint.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: Hint) it 'destroys the hint' do hint = FactoryBot.create(:ruby_syntax_error) - expect { delete :destroy, execution_environment_id: execution_environment.id, id: hint.id }.to change(Hint, :count).by(-1) + expect { delete :destroy, params: { execution_environment_id: execution_environment.id, id: hint.id } }.to change(Hint, :count).by(-1) end expect_redirect { execution_environment_hints_path(execution_environment) } end describe 'GET #edit' do - before(:each) { get :edit, execution_environment_id: execution_environment.id, id: hint.id } + before(:each) { get :edit, params: { execution_environment_id: execution_environment.id, id: hint.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: Hint) @@ -56,7 +56,7 @@ describe HintsController do describe 'GET #index' do before(:all) { FactoryBot.create_pair(:ruby_syntax_error) } - before(:each) { get :index, execution_environment_id: execution_environment.id } + before(:each) { get :index, params: { execution_environment_id: execution_environment.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hints: Hint.all) @@ -65,7 +65,7 @@ describe HintsController do end describe 'GET #new' do - before(:each) { get :new, execution_environment_id: execution_environment.id } + before(:each) { get :new, params: { execution_environment_id: execution_environment.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: Hint) @@ -74,7 +74,7 @@ describe HintsController do end describe 'GET #show' do - before(:each) { get :show, execution_environment_id: execution_environment.id, id: hint.id } + before(:each) { get :show, params: { execution_environment_id: execution_environment.id, id: hint.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: :hint) @@ -84,7 +84,7 @@ describe HintsController do describe 'PUT #update' do context 'with a valid hint' do - before(:each) { put :update, execution_environment_id: execution_environment.id, hint: FactoryBot.attributes_for(:ruby_syntax_error), id: hint.id } + before(:each) { put :update, params: { execution_environment_id: execution_environment.id, hint: FactoryBot.attributes_for(:ruby_syntax_error), id: hint.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: Hint) @@ -92,7 +92,7 @@ describe HintsController do end context 'with an invalid hint' do - before(:each) { put :update, execution_environment_id: execution_environment.id, hint: {name: ''}, id: hint.id } + before(:each) { put :update, params: { execution_environment_id: execution_environment.id, hint: {name: ''}, id: hint.id } } expect_assigns(execution_environment: :execution_environment) expect_assigns(hint: Hint) diff --git a/spec/controllers/internal_users_controller_spec.rb b/spec/controllers/internal_users_controller_spec.rb index 936852af..abb9c6d3 100644 --- a/spec/controllers/internal_users_controller_spec.rb +++ b/spec/controllers/internal_users_controller_spec.rb @@ -13,7 +13,7 @@ describe InternalUsersController do end context 'without a valid activation token' do - before(:each) { get :activate, id: user.id } + before(:each) { get :activate, params: { id: user.id } } expect_redirect(:root) end @@ -21,14 +21,14 @@ describe InternalUsersController do context 'with an already activated user' do before(:each) do user.activate! - get :activate, id: user.id, token: user.activation_token + get :activate, params: { id: user.id, token: user.activation_token } end expect_redirect(:root) end context 'with valid preconditions' do - before(:each) { get :activate, id: user.id, token: user.activation_token } + before(:each) { get :activate, params: { id: user.id, token: user.activation_token } } expect_assigns(user: InternalUser) expect_status(200) @@ -37,7 +37,7 @@ describe InternalUsersController do end describe 'PUT #activate' do - let(:user) { InternalUser.create(FactoryBot.attributes_for(:teacher)) } + let(:user) { InternalUser.create(FactoryBot.build(:teacher).attributes) } let(:password) { SecureRandom.hex } before(:each) do @@ -47,7 +47,7 @@ describe InternalUsersController do end context 'without a valid activation token' do - before(:each) { put :activate, id: user.id } + before(:each) { put :activate, params: { id: user.id } } expect_redirect(:root) end @@ -55,14 +55,14 @@ describe InternalUsersController do context 'with an already activated user' do before(:each) do user.activate! - put :activate, id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: password} + put :activate, params: { id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: password} } end expect_redirect(:root) end context 'without a password' do - before(:each) { put :activate, id: user.id, internal_user: {activation_token: user.activation_token} } + before(:each) { put :activate, params: { id: user.id, internal_user: {activation_token: user.activation_token} } } expect_assigns(user: InternalUser) @@ -74,7 +74,7 @@ describe InternalUsersController do end context 'without a valid password confirmation' do - before(:each) { put :activate, id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: ''} } + before(:each) { put :activate, params: { id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: ''} } } expect_assigns(user: InternalUser) @@ -86,7 +86,7 @@ describe InternalUsersController do end context 'with valid preconditions' do - before(:each) { put :activate, id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: password} } + before(:each) { put :activate, params: { id: user.id, internal_user: {activation_token: user.activation_token, password: password, password_confirmation: password} } } expect_assigns(user: InternalUser) @@ -103,7 +103,7 @@ describe InternalUsersController do before(:each) { allow(controller).to receive(:current_user).and_return(user) } context 'with a valid internal user' do - let(:request) { proc { post :create, internal_user: FactoryBot.attributes_for(:teacher) } } + let(:request) { proc { post :create, params: { internal_user: FactoryBot.build(:teacher).attributes } } } before(:each) { request.call } expect_assigns(user: InternalUser) @@ -129,7 +129,7 @@ describe InternalUsersController do end context 'with an invalid internal user' do - before(:each) { post :create, internal_user: {} } + before(:each) { post :create, params: { internal_user: {} } } expect_assigns(user: InternalUser) expect_status(200) @@ -140,13 +140,13 @@ describe InternalUsersController do describe 'DELETE #destroy' do before(:each) do allow(controller).to receive(:current_user).and_return(user) - delete :destroy, id: users.first.id + delete :destroy, params: { id: users.first.id } end expect_assigns(user: InternalUser) it 'destroys the internal user' do - expect { delete :destroy, id: InternalUser.last.id }.to change(InternalUser, :count).by(-1) + expect { delete :destroy, params: { id: InternalUser.last.id } }.to change(InternalUser, :count).by(-1) end expect_redirect(:internal_users) @@ -155,7 +155,7 @@ describe InternalUsersController do describe 'GET #edit' do before(:each) do allow(controller).to receive(:current_user).and_return(user) - get :edit, id: users.first.id + get :edit, params: { id: users.first.id } end expect_assigns(user: InternalUser) @@ -187,7 +187,7 @@ describe InternalUsersController do describe 'POST #forgot_password' do context 'with an email address' do - let(:request) { proc { post :forgot_password, email: user.email } } + let(:request) { proc { post :forgot_password, params: { email: user.email } } } before(:each) { request.call } it 'delivers instructions to reset the password' do @@ -233,7 +233,7 @@ describe InternalUsersController do let(:user) { users.first } context 'without a valid password reset token' do - before(:each) { get :reset_password, id: user.id } + before(:each) { get :reset_password, params: { id: user.id } } expect_redirect(:root) end @@ -241,7 +241,7 @@ describe InternalUsersController do context 'with a valid password reset token' do before(:each) do user.deliver_reset_password_instructions! - get :reset_password, id: user.id, token: user.reset_password_token + get :reset_password, params: { id: user.id, token: user.reset_password_token } end expect_assigns(user: :user) @@ -255,7 +255,7 @@ describe InternalUsersController do before(:each) { user.deliver_reset_password_instructions! } context 'without a valid password reset token' do - before(:each) { put :reset_password, id: user.id } + before(:each) { put :reset_password, params: { id: user.id } } expect_redirect(:root) end @@ -264,7 +264,7 @@ describe InternalUsersController do let(:password) { 'foo' } context 'with a matching password confirmation' do - let(:request) { proc { put :reset_password, internal_user: {password: password, password_confirmation: password}, id: user.id, token: user.reset_password_token } } + let(:request) { proc { put :reset_password, params: { internal_user: {password: password, password_confirmation: password}, id: user.id, token: user.reset_password_token } } } before(:each) { request.call } expect_assigns(user: :user) @@ -278,7 +278,7 @@ describe InternalUsersController do context 'without a matching password confirmation' do before(:each) do - put :reset_password, internal_user: {password: password, password_confirmation: ''}, id: users.first.id, token: user.reset_password_token + put :reset_password, params: { internal_user: {password: password, password_confirmation: ''}, id: users.first.id, token: user.reset_password_token } end expect_assigns(user: :user) @@ -291,7 +291,7 @@ describe InternalUsersController do describe 'GET #show' do before(:each) do allow(controller).to receive(:current_user).and_return(user) - get :show, id: users.first.id + get :show, params: { id: users.first.id } end expect_assigns(user: InternalUser) @@ -303,14 +303,14 @@ describe InternalUsersController do before(:each) { allow(controller).to receive(:current_user).and_return(user) } context 'with a valid internal user' do - before(:each) { put :update, internal_user: FactoryBot.attributes_for(:teacher), id: users.first.id } + before(:each) { put :update, params: { internal_user: FactoryBot.attributes_for(:teacher), id: users.first.id } } expect_assigns(user: InternalUser) expect_redirect { user } end context 'with an invalid internal user' do - before(:each) { put :update, internal_user: {email: ''}, id: users.first.id } + before(:each) { put :update, params: { internal_user: {email: ''}, id: users.first.id } } expect_assigns(user: InternalUser) expect_status(200) diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 17bd0721..a8feb5a2 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -4,14 +4,14 @@ describe SessionsController do let(:consumer) { FactoryBot.create(:consumer) } describe 'POST #create' do - let(:password) { user_attributes[:password] } - let(:user) { InternalUser.create(user_attributes) } - let(:user_attributes) { FactoryBot.attributes_for(:teacher) } + let(:password) { FactoryBot.attributes_for(:teacher)[:password] } + let(:user) { InternalUser.create(user_attributes.merge(password: password)) } + let(:user_attributes) { FactoryBot.build(:teacher).attributes } context 'with valid credentials' do before(:each) do user.activate! - post :create, email: user.email, password: password, remember_me: 1 + post :create, params: { email: user.email, password: password, remember_me: 1 } end expect_flash_message(:notice, :'sessions.create.success') @@ -19,7 +19,7 @@ describe SessionsController do end context 'with invalid credentials' do - before(:each) { post :create, email: user.email, password: '', remember_me: 1 } + before(:each) { post :create, params: { email: user.email, password: '', remember_me: 1 } } expect_flash_message(:danger, :'sessions.create.failure') expect_template(:new) @@ -42,14 +42,14 @@ describe SessionsController do context 'without a valid consumer key' do it 'refuses the LTI launch' do expect(controller).to receive(:refuse_lti_launch).with(message: I18n.t('sessions.oauth.invalid_consumer')).and_call_original - post :create_through_lti, oauth_consumer_key: SecureRandom.hex, oauth_signature: SecureRandom.hex + post :create_through_lti, params: { oauth_consumer_key: SecureRandom.hex, oauth_signature: SecureRandom.hex } end end context 'with an invalid OAuth signature' do it 'refuses the LTI launch' do expect(controller).to receive(:refuse_lti_launch).with(message: I18n.t('sessions.oauth.invalid_signature')).and_call_original - post :create_through_lti, oauth_consumer_key: consumer.oauth_key, oauth_signature: SecureRandom.hex + post :create_through_lti, params: { oauth_consumer_key: consumer.oauth_key, oauth_signature: SecureRandom.hex } end end @@ -58,7 +58,7 @@ describe SessionsController do expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:valid_request?).and_return(true) expect(NonceStore).to receive(:has?).with(nonce).and_return(true) expect(controller).to receive(:refuse_lti_launch).with(message: I18n.t('sessions.oauth.used_nonce')).and_call_original - post :create_through_lti, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex + post :create_through_lti, params: { oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex } end end @@ -66,13 +66,13 @@ describe SessionsController do it 'refuses the LTI launch' do expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:valid_request?).and_return(true) expect(controller).to receive(:refuse_lti_launch).with(message: I18n.t('sessions.oauth.invalid_exercise_token')).and_call_original - post :create_through_lti, custom_token: '', oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex + post :create_through_lti, params: { custom_token: '', oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex } end end context 'with valid launch parameters' do let(:locale) { :de } - let(:request) { post :create_through_lti, custom_locale: locale, custom_token: exercise.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id } + let(:request) { post :create_through_lti, params: { custom_locale: locale, custom_token: exercise.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id } } let(:user) { FactoryBot.create(:external_user, consumer_id: consumer.id) } before(:each) { expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:valid_request?).and_return(true) } @@ -134,7 +134,7 @@ describe SessionsController do it 'redirects to recommended exercise if requested token of proxy exercise' do skip 'test is currently oscillating' FactoryBot.create(:proxy_exercise, exercises: [exercise]) - post :create_through_lti, custom_locale: locale, custom_token: ProxyExercise.first.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id + post :create_through_lti, params: { custom_locale: locale, custom_token: ProxyExercise.first.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id } expect(controller).to redirect_to(implement_exercise_path(exercise.id)) end @@ -146,7 +146,7 @@ describe SessionsController do exercise.save exercise2.expected_difficulty = 1 exercise2.save - post :create_through_lti, custom_locale: locale, custom_token: ProxyExercise.first.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id + post :create_through_lti, params: { custom_locale: locale, custom_token: ProxyExercise.first.token, oauth_consumer_key: consumer.oauth_key, oauth_nonce: nonce, oauth_signature: SecureRandom.hex, user_id: user.external_id } expect(controller).to redirect_to(implement_exercise_path(exercise2.id)) end end @@ -192,7 +192,7 @@ describe SessionsController do end describe 'GET #destroy_through_lti' do - let(:request) { proc { get :destroy_through_lti, consumer_id: consumer.id, submission_id: submission.id } } + let(:request) { proc { get :destroy_through_lti, params: { consumer_id: consumer.id, submission_id: submission.id } } } let(:submission) { FactoryBot.create(:submission, exercise: FactoryBot.create(:dummy)) } before(:each) do diff --git a/spec/controllers/submissions_controller_spec.rb b/spec/controllers/submissions_controller_spec.rb index 2a3593c3..d059d795 100644 --- a/spec/controllers/submissions_controller_spec.rb +++ b/spec/controllers/submissions_controller_spec.rb @@ -12,7 +12,7 @@ describe SubmissionsController do context 'with a valid submission' do let(:exercise) { FactoryBot.create(:hello_world) } - let(:request) { proc { post :create, format: :json, submission: FactoryBot.attributes_for(:submission, exercise_id: exercise.id) } } + let(:request) { proc { post :create, format: :json, params: { submission: FactoryBot.attributes_for(:submission, exercise_id: exercise.id) } } } before(:each) { request.call } expect_assigns(submission: Submission) @@ -26,7 +26,7 @@ describe SubmissionsController do end context 'with an invalid submission' do - before(:each) { post :create, submission: {} } + before(:each) { post :create, params: { submission: { } } } expect_assigns(submission: Submission) expect_json @@ -36,21 +36,39 @@ describe SubmissionsController do describe 'GET #download_file' do context 'with an invalid filename' do - before(:each) { get :download_file, filename: SecureRandom.hex, id: submission.id } + before(:each) { get :download_file, params: { filename: SecureRandom.hex, id: submission.id } } expect_status(404) end + context 'with a valid binary filename' do + let(:submission) { FactoryBot.create(:submission, exercise: FactoryBot.create(:sql_select)) } + before(:each) { get :download_file, params: { filename: file.name_with_extension, id: submission.id } } + + context 'for a binary file' do + let(:file) { submission.collect_files.detect { |file| file.name == 'exercise' && file.file_type.file_extension == '.sql' } } + + expect_assigns(file: :file) + expect_assigns(submission: :submission) + expect_content_type('application/octet-stream') + expect_status(200) + + it 'sets the correct filename' do + expect(response.headers['Content-Disposition']).to eq("attachment; filename=\"#{file.name_with_extension}\"") + end + end + end + context 'with a valid filename' do let(:submission) { FactoryBot.create(:submission, exercise: FactoryBot.create(:audio_video)) } - before(:each) { get :download_file, filename: file.name_with_extension, id: submission.id } + before(:each) { get :download_file, params: { filename: file.name_with_extension, id: submission.id } } context 'for a binary file' do let(:file) { submission.collect_files.detect { |file| file.file_type.file_extension == '.mp4' } } expect_assigns(file: :file) expect_assigns(submission: :submission) - expect_content_type('application/octet-stream') + expect_content_type('video/mp4') expect_status(200) it 'sets the correct filename' do @@ -86,21 +104,21 @@ describe SubmissionsController do let(:file) { submission.files.first } context 'with an invalid filename' do - before(:each) { get :render_file, filename: SecureRandom.hex, id: submission.id } + before(:each) { get :render_file, params: { filename: SecureRandom.hex, id: submission.id } } expect_status(404) end context 'with a valid filename' do let(:submission) { FactoryBot.create(:submission, exercise: FactoryBot.create(:audio_video)) } - before(:each) { get :render_file, filename: file.name_with_extension, id: submission.id } + before(:each) { get :render_file, params: { filename: file.name_with_extension, id: submission.id } } context 'for a binary file' do let(:file) { submission.collect_files.detect { |file| file.file_type.file_extension == '.mp4' } } expect_assigns(file: :file) expect_assigns(submission: :submission) - expect_content_type('application/octet-stream') + expect_content_type('video/mp4') expect_status(200) it 'renders the file content' do @@ -125,7 +143,7 @@ describe SubmissionsController do describe 'GET #run' do let(:filename) { submission.collect_files.detect(&:main_file?).name_with_extension } - let(:request) { get :run, filename: filename, id: submission.id } + let(:request) { get :run, params: { filename: filename }, id: submission.id } before(:each) do expect_any_instance_of(ActionController::Live::SSE).to receive(:write).at_least(3).times @@ -176,7 +194,7 @@ describe SubmissionsController do end describe 'GET #show' do - before(:each) { get :show, id: submission.id } + before(:each) { get :show, params: { id: submission.id } } expect_assigns(submission: :submission) expect_status(200) @@ -188,7 +206,7 @@ describe SubmissionsController do # https://github.com/rails/jbuilder/issues/32 render_views - before(:each) { get :show, id: submission.id, format: :json } + before(:each) { get :show, params: { id: submission.id }, format: :json } expect_assigns(submission: :submission) expect_status(200) @@ -219,14 +237,14 @@ describe SubmissionsController do end describe 'GET #score' do - let(:request) { proc { get :score, id: submission.id } } + let(:request) { proc { get :score, params: { id: submission.id } } } before(:each) { request.call } pending("todo: mock puma webserver or encapsulate tubesock call (Tubesock::HijackNotAvailable)") end describe 'POST #stop' do - let(:request) { proc { post :stop, container_id: CONTAINER.id, id: submission.id } } + let(:request) { proc { post :stop, params: { container_id: CONTAINER.id, id: submission.id } } } context 'when the container can be found' do before(:each) do @@ -269,7 +287,7 @@ describe SubmissionsController do end describe '#with_server_sent_events' do - let(:response) { ActionController::TestResponse.new } + let(:response) { ActionDispatch::TestResponse.new } before(:each) { allow(controller).to receive(:response).and_return(response) } context 'when no error occurs' do diff --git a/spec/factories/error_templates.rb b/spec/factories/error_templates.rb index 222cf363..41286229 100644 --- a/spec/factories/error_templates.rb +++ b/spec/factories/error_templates.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :error_template do - execution_environment { nil } + association :execution_environment, factory: :ruby name { "MyString" } signature { "MyString" } end diff --git a/spec/factories/internal_user.rb b/spec/factories/internal_user.rb index 7bcf629c..5dec652e 100644 --- a/spec/factories/internal_user.rb +++ b/spec/factories/internal_user.rb @@ -1,6 +1,7 @@ FactoryBot.define do factory :admin, class: InternalUser do activated_user + association :consumer email { 'admin@example.org' } generated_user_name password { 'admin' } diff --git a/spec/factories/structured_error_attributes.rb b/spec/factories/structured_error_attributes.rb index 27d0330e..5652f1b6 100644 --- a/spec/factories/structured_error_attributes.rb +++ b/spec/factories/structured_error_attributes.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :structured_error_attribute do - structured_error { nil } - error_template_attribute { nil } + association :structured_error + association :error_template_attribute value { "MyString" } end end diff --git a/spec/factories/structured_errors.rb b/spec/factories/structured_errors.rb index 33cab151..2b61e744 100644 --- a/spec/factories/structured_errors.rb +++ b/spec/factories/structured_errors.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :structured_error do - error_template { nil } - submission { nil } + association :error_template + association :submission end end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index d89b646c..59962280 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -37,6 +37,11 @@ describe UserMailer do describe '#reset_password_email' do let(:mail) { described_class.reset_password_email(user) } + before(:each) do + user.send(:setup_activation) + user.save(validate: false) + end + it 'sets the correct sender' do expect(mail.from).to include(CodeOcean::Application.config.action_mailer[:default_options][:from]) end diff --git a/spec/policies/exercise_policy_spec.rb b/spec/policies/exercise_policy_spec.rb index f0024fa8..49afe05a 100644 --- a/spec/policies/exercise_policy_spec.rb +++ b/spec/policies/exercise_policy_spec.rb @@ -75,7 +75,7 @@ let(:exercise) { FactoryBot.build(:dummy) } [@admin, @teacher].each do |user| [true, false].each do |public| - FactoryBot.create(:dummy, public: public, user_id: user.id, user_type: InternalUser.class.name) + FactoryBot.create(:dummy, public: public, user_id: user.id, user_type: InternalUser.name) end end end diff --git a/spec/support/selenium.rb b/spec/support/selenium.rb index 4aeb28de..8f722dbd 100644 --- a/spec/support/selenium.rb +++ b/spec/support/selenium.rb @@ -8,6 +8,9 @@ if ENV['HEADLESS_TEST'] == 'true' || ENV['USER'] == 'vagrant' headless.start end +#Capybara.server = :webrick +# Capybara.server_port = 3333 + Capybara.register_driver :selenium do |app| profile = Selenium::WebDriver::Firefox::Profile.new profile['intl.accept_languages'] = 'en' @@ -15,7 +18,7 @@ Capybara.register_driver :selenium do |app| options = Selenium::WebDriver::Firefox::Options.new options.profile = profile driver = Capybara::Selenium::Driver.new(app, browser: :firefox, desired_capabilities: capabilities, options: options) - driver.browser.manage.window.resize_to(1280, 960) + #driver.browser.manage.window.resize_to(1280, 960) driver end Capybara.javascript_driver = :selenium diff --git a/public/javascripts/bootstrap.min.js b/vendor/assets/javascripts/bootstrap.min.js similarity index 100% rename from public/javascripts/bootstrap.min.js rename to vendor/assets/javascripts/bootstrap.min.js diff --git a/public/javascripts/underscore-min.js b/vendor/assets/javascripts/underscore.min.js similarity index 100% rename from public/javascripts/underscore-min.js rename to vendor/assets/javascripts/underscore.min.js diff --git a/public/javascripts/vis.min.js b/vendor/assets/javascripts/vis.min.js similarity index 100% rename from public/javascripts/vis.min.js rename to vendor/assets/javascripts/vis.min.js diff --git a/public/stylesheets/bootstrap.min.css b/vendor/assets/stylesheets/bootstrap.min.css similarity index 100% rename from public/stylesheets/bootstrap.min.css rename to vendor/assets/stylesheets/bootstrap.min.css diff --git a/public/stylesheets/font-awesome.min.css b/vendor/assets/stylesheets/font-awesome.min.css similarity index 100% rename from public/stylesheets/font-awesome.min.css rename to vendor/assets/stylesheets/font-awesome.min.css diff --git a/public/stylesheets/google_opensans.css b/vendor/assets/stylesheets/google_opensans.css similarity index 100% rename from public/stylesheets/google_opensans.css rename to vendor/assets/stylesheets/google_opensans.css diff --git a/public/stylesheets/vis.min.css b/vendor/assets/stylesheets/vis.min.css similarity index 100% rename from public/stylesheets/vis.min.css rename to vendor/assets/stylesheets/vis.min.css