From 8aaf93af6b2da5f6abdab950355e63cc027639c2 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 13:38:17 +0200 Subject: [PATCH 01/14] Remove JS debugger statement --- app/assets/javascripts/editor/evaluation.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/editor/evaluation.js b/app/assets/javascripts/editor/evaluation.js index 186edc44..7000a3b7 100644 --- a/app/assets/javascripts/editor/evaluation.js +++ b/app/assets/javascripts/editor/evaluation.js @@ -39,7 +39,6 @@ CodeOceanEditorEvaluation = { $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_within_grace_period'); } else if (this.late_submission_deadline && now > this.late_submission_deadline || now > this.submission_deadline) { // after_late_deadline - debugger; $('#submit').removeClass("btn-success btn-warning btn-danger").addClass("btn-danger"); $('#submit').get(0).lastChild.nodeValue = I18n.t('exercises.editor.submit_after_late_deadline'); } From fb7d0eafe86ef5be527f5013554cc5bb76303f3a Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 13:41:20 +0200 Subject: [PATCH 02/14] Fix permission check for exercises --- app/policies/application_policy.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index a162c368..28f33b7c 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -26,16 +26,17 @@ class ApplicationPolicy private :no_one def everyone_in_study_group + # !! Order is important !! if @record.respond_to? :study_group # e.g. submission study_group = @record.study_group return false if study_group.blank? users_in_same_study_group = study_group.users - elsif @record.respond_to? :users # e.g. study_group - users_in_same_study_group = @record.users elsif @record.respond_to? :user # e.g. exercise study_groups = @record.user.study_groups users_in_same_study_group = study_groups.collect(&:users).flatten + elsif @record.respond_to? :users # e.g. study_group + users_in_same_study_group = @record.users elsif @record.respond_to? :study_groups # e.g. user study_groups = @record.study_groups users_in_same_study_group = study_groups.collect(&:users).flatten From 8c9a1390d4ce7100636f83791d1140b069b7dbb1 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 13:41:44 +0200 Subject: [PATCH 03/14] Make UserExerciseFeedback look nice again --- app/views/user_exercise_feedbacks/_form.html.slim | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/views/user_exercise_feedbacks/_form.html.slim b/app/views/user_exercise_feedbacks/_form.html.slim index a5fbf63a..acb3cdf5 100644 --- a/app/views/user_exercise_feedbacks/_form.html.slim +++ b/app/views/user_exercise_feedbacks/_form.html.slim @@ -13,10 +13,16 @@ .form-group = f.text_area(:feedback_text, class: 'form-control', required: true, :rows => "10") h4.mt-4 = t('user_exercise_feedback.difficulty') - = f.collection_radio_buttons :difficulty, @texts, :first, :last, html_options: {class: "form-check-inline"} do |b| - = b.label(:class => 'form-check') { b.radio_button + b.text } + = f.collection_radio_buttons :difficulty, @texts, :first, :last do |b| + .form-check + label.form-check-label + = b.radio_button(class: 'form-check-input') + = b.text h4.mt-4 = t('user_exercise_feedback.working_time') - = f.collection_radio_buttons :user_estimated_worktime, @times, :first, :last, html_options: {class: "form-check-inline"} do |b| - = b.label(:class => 'form-check') { b.radio_button + b.text } + = f.collection_radio_buttons :user_estimated_worktime, @times, :first, :last do |b| + .form-check + label.form-check-label + = b.radio_button(class: 'form-check-input') + = b.text = f.hidden_field(:exercise_id, :value => @exercise.id) .actions = render('shared/submit_button', f: f, object: @uef) From 1ec345d47d658bfdc29d4547bd34407255faef03 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 13:42:22 +0200 Subject: [PATCH 04/14] Fix deadline information on exercise statistics --- app/views/exercises/statistics.html.slim | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index 4422d4f1..97757feb 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -42,8 +42,7 @@ h1 = @exercise - submissions = Submission.where(user: @exercise.send(symbol).distinct, exercise: @exercise).in_study_group_of(current_user) - if !policy(@exercise).detailed_statistics? - submissions = submissions.final - - latest_submission = submissions.latest - - if latest_submission + - if submissions.any? .table-responsive table.table.table-striped.sortable thead @@ -61,12 +60,13 @@ h1 = @exercise tr td = link_to_if symbol==:external_users && policy(user).statistics?, label, {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id} td = us['maximum_score'] or 0 - td.align-middle - - if latest_submission.before_deadline? + td.align-middle + - latest_user_submission = submissions.where(user: user).latest + - if latest_user_submission.before_deadline? .unit-test-result.positive-result.before_deadline - - elsif latest_submission.within_grace_period? + - elsif latest_user_submission.within_grace_period? .unit-test-result.unknown-result.within_grace_period - - elsif latest_submission.after_late_deadline? + - elsif latest_user_submission.after_late_deadline? .unit-test-result.negative-result.after_late_deadline td = us['runs'] if policy(@exercise).detailed_statistics? td = @exercise.average_working_time_for(user.id) or 0 if policy(@exercise).detailed_statistics? From b6db9e186c1c35f55ce68ad8b1b64e9c3e49d302 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 13:44:28 +0200 Subject: [PATCH 05/14] Add information if execution timed out during scoring --- app/controllers/concerns/submission_scoring.rb | 4 ++++ config/locales/de.yml | 1 + config/locales/en.yml | 1 + lib/docker_client.rb | 8 +++++--- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index 2e932631..8dfa90b8 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -56,6 +56,10 @@ module SubmissionScoring unless output.nil? score += output[:score] * output[:weight] end + + if output[:status] == :timeout + output[:stderr] += "\n\n#{t('exercises.editor.timeout', permitted_execution_time: submission.exercise.execution_environment.permitted_execution_time.to_s)}" + end end end submission.update(score: score) diff --git a/config/locales/de.yml b/config/locales/de.yml index d628c81d..88b338fe 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -431,6 +431,7 @@ de: finishing_rate: Abschlussrate submit: failure: Beim Übermitteln Ihrer Punktzahl ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut. + too_late: Ihre Abgabe wurde erfolgreich gespeichert, ging jedoch nach der Abgabefrist ein. full_score_redirect_to_rfc: Herzlichen Glückwunsch! Sie haben die maximale Punktzahl für diese Aufgabe an den Kurs übertragen. Ein anderer Teilnehmer hat eine Frage zu der von Ihnen gelösten Aufgabe. Er würde sich sicherlich sehr über ihre Hilfe und Kommentare freuen. full_score_redirect_to_own_rfc: Herzlichen Glückwunsch! Sie haben die maximale Punktzahl für diese Aufgabe an den Kurs übertragen. Ihre Frage ist damit wahrscheinlich gelöst? Falls ja, fügen Sie doch den entscheidenden Kniff als Antwort hinzu und markieren die Frage als gelöst, bevor sie das Fenster schließen. study_group_dashboard: diff --git a/config/locales/en.yml b/config/locales/en.yml index 30442d38..db8bfa6e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -431,6 +431,7 @@ en: finishing_rate: Finishing Rate submit: failure: An error occurred while transmitting your score. Please try again later. + too_late: Your submission was saved successfully but was received after the deadline passed. full_score_redirect_to_rfc: Congratulations! You achieved and submitted the highest possible score for this exercise. Another participant has a question concerning the exercise you just solved. Your help and comments will be greatly appreciated! full_score_redirect_to_own_rfc: Congratulations! You achieved and submitted the highest possible score for this exercise. Your question concerning the exercise is solved? If so, please share the essential insight with your fellows and mark the question as solved, before you close this window! study_group_dashboard: diff --git a/lib/docker_client.rb b/lib/docker_client.rb index cc65a3ed..a5d3f5df 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -450,9 +450,9 @@ class DockerClient def send_command(command, container) result = {status: :failed, stdout: '', stderr: ''} output = nil - Timeout.timeout(@execution_environment.permitted_execution_time.to_i) do + Timeout.timeout(@execution_environment.permitted_execution_time.to_i - 29) do # TODO: check phusion doku again if we need -i -t options here - output = container.exec(['bash', '-c', command]) + output = container.exec(['bash', '-c', "#{command} > /proc/1/fd/1 2> /proc/1/fd/2"], tty: false) end Rails.logger.debug 'output from container.exec' Rails.logger.debug output @@ -467,8 +467,10 @@ class DockerClient result rescue Timeout::Error Rails.logger.info('got timeout error for container ' + container.to_s) + stdout = container.logs(stdout: true).force_encoding('utf-8').gsub(/.*\/workspace\$\ /, '') + stderr = container.logs(stderr: true).force_encoding('utf-8').gsub(/.*\/workspace\$\ /, '') kill_container(container) - {status: :timeout} + {status: :timeout, stdout: stdout, stderr: stderr} end private :send_command From 564b249e50fcfaab8bddd334bb9f2a4045b9e007 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 13:53:46 +0200 Subject: [PATCH 06/14] Refactor send_score to have access to the submission --- app/controllers/concerns/lti.rb | 22 ++++++++++++---------- app/controllers/exercises_controller.rb | 6 +++++- spec/concerns/lti_spec.rb | 15 ++++++++++----- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/app/controllers/concerns/lti.rb b/app/controllers/concerns/lti.rb index b19f885c..62e2899d 100644 --- a/app/controllers/concerns/lti.rb +++ b/app/controllers/concerns/lti.rb @@ -16,8 +16,8 @@ module Lti private :build_tool_provider - # exercise_id.nil? ==> the user has logged out. All session data is to be destroyed - # exercise_id.exists? ==> the user has submitted the results of an exercise to the consumer. + # @submission.exercise_id.nil? ==> the user has logged out. All session data is to be destroyed + # @submission.exercise_id.exists? ==> the user has submitted the results of an exercise to the consumer. # Only the lti_parameters are deleted. def clear_lti_session_data(exercise_id = nil, user_id = nil, consumer_id = nil) if (exercise_id.nil?) @@ -138,14 +138,14 @@ module Lti private :return_to_consumer - def send_score(exercise_id, score, user_id) - ::NewRelic::Agent.add_custom_attributes({score: score, session: session}) - fail(Error, "Score #{score} must be between 0 and #{MAXIMUM_SCORE}!") unless (0..MAXIMUM_SCORE).include?(score) + def send_score(submission) + ::NewRelic::Agent.add_custom_attributes({score: submission.normalized_score, session: session}) + fail(Error, "Score #{submission.normalized_score} must be between 0 and #{MAXIMUM_SCORE}!") unless (0..MAXIMUM_SCORE).include?(submission.normalized_score) if session[:consumer_id] lti_parameter = LtiParameter.where(consumers_id: session[:consumer_id], - external_users_id: user_id, - exercises_id: exercise_id).last + external_users_id: submission.user_id, + exercises_id: submission.exercise_id).last consumer = Consumer.find_by(id: session[:consumer_id]) provider = build_tool_provider(consumer: consumer, parameters: lti_parameter.lti_parameters) @@ -153,15 +153,17 @@ module Lti if provider.nil? {status: 'error'} + elsif submission.after_late_deadline? + {status: 'too late'} elsif provider.outcome_service? Raven.extra_context({ provider: provider.inspect, - score: score, + score: submission.normalized_score, lti_parameter: lti_parameter.inspect, session: session.to_hash, - exercise_id: exercise_id + exercise_id: submission.exercise_id }) - response = provider.post_replace_result!(score) + response = provider.post_replace_result!(submission.normalized_score) {code: response.response_code, message: response.post_response.body, status: response.code_major} else {status: 'unsupported'} diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 55afc796..c8c137b9 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -459,10 +459,14 @@ class ExercisesController < ApplicationController def transmit_lti_score ::NewRelic::Agent.add_custom_attributes({submission: @submission.id, normalized_score: @submission.normalized_score}) - response = send_score(@submission.exercise_id, @submission.normalized_score, @submission.user_id) + response = send_score(@submission) if response[:status] == 'success' redirect_after_submit + elsif response[:status] == 'too late' + flash[:warning] = I18n.t('exercises.submit.too_late') + flash.keep(:warning) + redirect_after_submit else respond_to do |format| format.html { redirect_to(implement_exercise_path(@submission.exercise)) } diff --git a/spec/concerns/lti_spec.rb b/spec/concerns/lti_spec.rb index e184539e..ab02327a 100644 --- a/spec/concerns/lti_spec.rb +++ b/spec/concerns/lti_spec.rb @@ -105,7 +105,8 @@ describe Lti do context 'with an invalid score' do it 'raises an exception' do - expect { controller.send(:send_score, submission.exercise_id, Lti::MAXIMUM_SCORE * 2, submission.user_id) }.to raise_error(Lti::Error) + allow(submission).to receive(:normalized_score).and_return Lti::MAXIMUM_SCORE * 2 + expect { controller.send(:send_score, submission) }.to raise_error(Lti::Error) end end @@ -118,7 +119,8 @@ describe Lti do context 'when grading is not supported' do it 'returns a corresponding status' do expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:outcome_service?).and_return(false) - expect(controller.send(:send_score, submission.exercise_id, score, submission.user_id)[:status]).to eq('unsupported') + allow(submission).to receive(:normalized_score).and_return score + expect(controller.send(:send_score, submission)[:status]).to eq('unsupported') end end @@ -135,11 +137,13 @@ describe Lti do end it 'sends the score' do - controller.send(:send_score, submission.exercise_id, score, submission.user_id) + allow(submission).to receive(:normalized_score).and_return score + controller.send(:send_score, submission) end it 'returns code, message, and status' do - result = controller.send(:send_score, submission.exercise_id, score, submission.user_id) + allow(submission).to receive(:normalized_score).and_return score + result = controller.send(:send_score, submission) expect(result[:code]).to eq(response.response_code) expect(result[:message]).to eq(response.body) expect(result[:status]).to eq(response.code_major) @@ -149,7 +153,8 @@ describe Lti do context 'without a tool consumer' do it 'returns a corresponding status' do - expect(controller.send(:send_score, submission.exercise_id, score, submission.user_id)[:status]).to eq('error') + allow(submission).to receive(:normalized_score).and_return score + expect(controller.send(:send_score, submission)[:status]).to eq('error') end end end From daa39336fb409a4033ea8bc56f50ce9d97a98345 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 14:19:18 +0200 Subject: [PATCH 07/14] Fix happy path for scoring --- lib/docker_client.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/docker_client.rb b/lib/docker_client.rb index a5d3f5df..85972135 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -452,7 +452,8 @@ class DockerClient output = nil Timeout.timeout(@execution_environment.permitted_execution_time.to_i - 29) do # TODO: check phusion doku again if we need -i -t options here - output = container.exec(['bash', '-c', "#{command} > /proc/1/fd/1 2> /proc/1/fd/2"], tty: false) + # https://stackoverflow.com/questions/363223/how-do-i-get-both-stdout-and-stderr-to-go-to-the-terminal-and-a-log-file + output = container.exec(['bash', '-c', "#{command} 1> >(tee /proc/1/fd/1) 2> >(tee /proc/1/fd/2 >&2)"], tty: false) end Rails.logger.debug 'output from container.exec' Rails.logger.debug output From d912062abdc829dbe67abe86a08b70ba309791b2 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 17:38:42 +0200 Subject: [PATCH 08/14] Copy output to file and stdout / stderr --- lib/docker_client.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 85972135..3b06f877 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -450,10 +450,10 @@ class DockerClient def send_command(command, container) result = {status: :failed, stdout: '', stderr: ''} output = nil - Timeout.timeout(@execution_environment.permitted_execution_time.to_i - 29) do + Timeout.timeout(@execution_environment.permitted_execution_time.to_i) do # TODO: check phusion doku again if we need -i -t options here # https://stackoverflow.com/questions/363223/how-do-i-get-both-stdout-and-stderr-to-go-to-the-terminal-and-a-log-file - output = container.exec(['bash', '-c', "#{command} 1> >(tee /proc/1/fd/1) 2> >(tee /proc/1/fd/2 >&2)"], tty: false) + output = container.exec(['bash', '-c', "#{command} 1> >(tee -a /tmp/stdout.log) 2> >(tee -a /tmp/stderr.log >&2); rm /tmp/std*.log"], tty: false) end Rails.logger.debug 'output from container.exec' Rails.logger.debug output @@ -468,8 +468,8 @@ class DockerClient result rescue Timeout::Error Rails.logger.info('got timeout error for container ' + container.to_s) - stdout = container.logs(stdout: true).force_encoding('utf-8').gsub(/.*\/workspace\$\ /, '') - stderr = container.logs(stderr: true).force_encoding('utf-8').gsub(/.*\/workspace\$\ /, '') + stdout = container.exec(['cat', '/tmp/stdout.log'])[0].join.force_encoding('utf-8') + stderr = container.exec(['cat', '/tmp/stderr.log'])[0].join.force_encoding('utf-8') kill_container(container) {status: :timeout, stdout: stdout, stderr: stderr} end From fece760132eba8cb666cc38770123b837f28058d Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 17:40:54 +0200 Subject: [PATCH 09/14] Update bundle and move jquery_ujs --- Gemfile | 1 - Gemfile.lock | 15 +++------ app/assets/javascripts/application.js | 1 - app/javascript/packs/application.js | 1 + package.json | 1 + yarn.lock | 47 +++++++++++++++------------ 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Gemfile b/Gemfile index 34e6dbcf..abae97ce 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,6 @@ gem 'factory_bot_rails' gem 'forgery' gem 'highline' gem 'jbuilder' -gem 'jquery-rails' gem 'ims-lti', '< 2.0.0' gem 'kramdown' gem 'pg' diff --git a/Gemfile.lock b/Gemfile.lock index 7d518706..4743c830 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -155,13 +155,8 @@ GEM ims-lti (1.2.4) builder (>= 1.0, < 4.0) oauth (>= 0.4.5, < 0.6) - jaro_winkler (1.5.4) jbuilder (2.10.0) activesupport (>= 5.0.0) - jquery-rails (4.4.0) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) json (2.3.0) jwt (2.2.1) kramdown (2.2.1) @@ -228,7 +223,7 @@ GEM pry (~> 0.13.0) pry-rails (0.3.9) pry (>= 0.10.4) - public_suffix (4.0.4) + public_suffix (4.0.5) puma (4.3.3) nio4r (~> 2.0) pundit (2.1.0) @@ -301,7 +296,7 @@ GEM rspec-expectations (>= 2.99.0.beta1) rspec-core (3.9.2) rspec-support (~> 3.9.3) - rspec-expectations (3.9.1) + rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) rspec-mocks (3.9.1) @@ -316,8 +311,7 @@ GEM rspec-mocks (~> 3.9) rspec-support (~> 3.9) rspec-support (3.9.3) - rubocop (0.82.0) - jaro_winkler (~> 1.5.1) + rubocop (0.83.0) parallel (~> 1.10) parser (>= 2.7.0.1) rainbow (>= 2.2.2, < 4.0) @@ -356,7 +350,7 @@ GEM docile (~> 1.1) simplecov-html (~> 0.11) simplecov-html (0.12.2) - slim (4.0.1) + slim (4.1.0) temple (>= 0.7.6, < 0.9) tilt (>= 2.0.6, < 2.1) slim-rails (3.2.0) @@ -443,7 +437,6 @@ DEPENDENCIES i18n-js ims-lti (< 2.0.0) jbuilder - jquery-rails kramdown listen mnemosyne-ruby diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 78028ff2..16c88a1d 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -10,7 +10,6 @@ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details // about supported directives. // -//= require jquery_ujs //= require turbolinks //= require pagedown_bootstrap //= require rails-timeago diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 139d205b..8e0bd22d 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -9,6 +9,7 @@ // JS import 'jquery'; +import 'jquery-ujs' import 'bootstrap/dist/js/bootstrap.bundle.min'; import 'chosen-js/chosen.jquery'; import 'jstree'; diff --git a/package.json b/package.json index 41c47694..965994a8 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "highlight.js": "^10.0.3", "jquery": "^3.5.1", "jquery-ui": "^1.12.1", + "jquery-ujs": "^1.2.2", "jstree": "^3.3.9", "opensans-webkit": "^1.1.0", "popper.js": "^1.16.1", diff --git a/yarn.lock b/yarn.lock index cb9afffd..f469c5ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1720,9 +1720,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043: - version "1.0.30001053" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001053.tgz#b7ae027567ce2665b965b0437e4512b296ccd20d" - integrity sha512-HtV4wwIZl6GA4Oznse8aR274XUOYGZnQLcf/P8vHgmlfqSNelwD+id8CyHOceqLqt9yfKmo7DUZTh1EuS9pukg== + version "1.0.30001055" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001055.tgz#7b52c3537f7a8c0408aca867e83d2b04268b54cd" + integrity sha512-MbwsBmKrBSKIWldfdIagO5OJWZclpJtS4h0Jrk/4HFrXJxTdVdH23Fd+xCiHriVGvYcWyW8mR/CPsYajlH8Iuw== case-sensitive-paths-webpack-plugin@^2.3.0: version "2.3.0" @@ -2804,9 +2804,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.3.413: - version "1.3.430" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.430.tgz#33914f7c2db771bdcf30977bd4fd6258ee8a2f37" - integrity sha512-HMDYkANGhx6vfbqpOf/hc6hWEmiOipOHGDeRDeUb3HLD3XIWpvKQxFgWf0tgHcr3aNv6I/8VPecplqmQsXoZSw== + version "1.3.434" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.434.tgz#a67dcb268e93768e2169399999ccffa4783f048e" + integrity sha512-WjzGrE6appXvMyc2kH9Ide7OxsgTuRzag9sjQ5AcbOnbS9ut7P1HzOeEbJFLhr81IR7n2Hlr6qTTSGTXLIX5Pg== elliptic@^6.0.0, elliptic@^6.5.2: version "6.5.2" @@ -2872,9 +2872,9 @@ enhanced-resolve@^4.1.0: tapable "^1.0.0" entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436" + integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw== errno@^0.1.3, errno@~0.1.7: version "0.1.7" @@ -2962,9 +2962,9 @@ etag@~1.8.1: integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eventemitter3@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" - integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== events@^3.0.0: version "3.1.0" @@ -3587,7 +3587,7 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight.js@^10.0.3: +highlight.js@^10.0.2: version "10.0.3" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.0.3.tgz#5effcc58420f113f279a0badb8ac50c4be06e63b" integrity sha512-9FG7SSzv9yOY5CGGxfI6NDm7xLYtMOjKtPBxw7Zff3t5UcRcUNTGEeS8lNjhceL34KeetLMoGMFTGoaa83HwyQ== @@ -4172,7 +4172,14 @@ jquery-ui@^1.12.1: resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.12.1.tgz#bcb4045c8dd0539c134bc1488cdd3e768a7a9e51" integrity sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE= -jquery@>=1.9.1, jquery@^3.5.1: +jquery-ujs@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jquery-ujs/-/jquery-ujs-1.2.2.tgz#6a8ef1020e6b6dda385b90a4bddc128c21c56397" + integrity sha1-ao7xAg5rbdo4W5CkvdwSjCHFY5c= + dependencies: + jquery ">=1.8.0" + +jquery@>=1.8.0, jquery@>=1.9.1, jquery@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5" integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== @@ -6093,9 +6100,9 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: uniq "^1.0.1" postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.29" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.29.tgz#d3a903872bd52280b83bce38cdc83ce55c06129e" - integrity sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw== + version "7.0.30" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2" + integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -6557,9 +6564,9 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-regex@^1.1.0: version "1.1.0" From 5547ff5ac5b086259b1e05eeadc493b2f52d8ce3 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 17:54:37 +0200 Subject: [PATCH 10/14] Fix comment --- app/controllers/concerns/lti.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/concerns/lti.rb b/app/controllers/concerns/lti.rb index 62e2899d..45c3d9db 100644 --- a/app/controllers/concerns/lti.rb +++ b/app/controllers/concerns/lti.rb @@ -16,8 +16,8 @@ module Lti private :build_tool_provider - # @submission.exercise_id.nil? ==> the user has logged out. All session data is to be destroyed - # @submission.exercise_id.exists? ==> the user has submitted the results of an exercise to the consumer. + # exercise_id.nil? ==> the user has logged out. All session data is to be destroyed + # exercise_id.exists? ==> the user has submitted the results of an exercise to the consumer. # Only the lti_parameters are deleted. def clear_lti_session_data(exercise_id = nil, user_id = nil, consumer_id = nil) if (exercise_id.nil?) From 24823c813bd5fc5db3d0ec15b719fa3cb9d35303 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 17:54:48 +0200 Subject: [PATCH 11/14] Update highlight.js --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index f469c5ec..01c594b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3587,7 +3587,7 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight.js@^10.0.2: +highlight.js@^10.0.3: version "10.0.3" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.0.3.tgz#5effcc58420f113f279a0badb8ac50c4be06e63b" integrity sha512-9FG7SSzv9yOY5CGGxfI6NDm7xLYtMOjKtPBxw7Zff3t5UcRcUNTGEeS8lNjhceL34KeetLMoGMFTGoaa83HwyQ== From df8ea4045c98539a2400bc1f93e76d1f7269c3f9 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 18:20:29 +0200 Subject: [PATCH 12/14] Fix spec --- spec/lib/docker_client_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/lib/docker_client_spec.rb b/spec/lib/docker_client_spec.rb index 8bb7a975..4cc8ce26 100644 --- a/spec/lib/docker_client_spec.rb +++ b/spec/lib/docker_client_spec.rb @@ -369,7 +369,10 @@ describe DockerClient, docker: true do end context 'when a timeout occurs' do - before(:each) { expect(container).to receive(:exec).and_raise(Timeout::Error) } + before(:each) do + expect(container).to receive(:exec).once.and_raise(Timeout::Error) + expect(container).to receive(:exec).twice.and_return([ [], [] ]) + end it 'destroys the container asynchronously' do pending("Container is destroyed, but not as expected in this test. ToDo update this test.") From 75b076767782e5a250b644bde38e27722e303d99 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 18:34:09 +0200 Subject: [PATCH 13/14] Fix feedback page --- app/views/exercises/feedback.html.slim | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/views/exercises/feedback.html.slim b/app/views/exercises/feedback.html.slim index 7c28eabc..4b4e7b89 100644 --- a/app/views/exercises/feedback.html.slim +++ b/app/views/exercises/feedback.html.slim @@ -24,12 +24,14 @@ h1 = link_to_if(policy(@exercise).show?, @exercise, exercise_path(@exercise)) span.date = feedback.created_at .card-collapse role="tabpanel" .card-body.feedback - .text = feedback.feedback_text + .text = render_markdown(feedback.feedback_text) .difficulty = "#{t('user_exercise_feedback.difficulty')} #{comment_presets[feedback.difficulty].join(' - ')}" if feedback.difficulty .worktime = "#{t('user_exercise_feedback.working_time')} #{time_presets[feedback.user_estimated_worktime].join(' - ')}" if feedback.user_estimated_worktime - .card-footer - span.points = "#{t('exercises.statistics.score')}: #{@submissions[index].score}" - span.working_time.pull-right = "#{t('exercises.statistics.worktime')}: #{@exercise.average_working_time_for(feedback.user.id) or 0}" + - if policy(@exercise).detailed_statistics? + .card-footer + div.clearfix.feedback-header + span.points.flex-grow-1 = "#{t('exercises.statistics.score')}: #{@submissions[index].score}" + span.working_time.pull-right = "#{t('exercises.statistics.worktime')}: #{@exercise.average_working_time_for(feedback.user.id) or 0}" = render('shared/pagination', collection: @feedbacks) From 2b7170b2028d0afeec78ae4d84ed882858012d57 Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 12 May 2020 18:52:08 +0200 Subject: [PATCH 14/14] better error handling --- app/controllers/concerns/submission_scoring.rb | 2 +- lib/docker_client.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index 8dfa90b8..9cbb2c0f 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -57,7 +57,7 @@ module SubmissionScoring score += output[:score] * output[:weight] end - if output[:status] == :timeout + if output.present? && output[:status] == :timeout output[:stderr] += "\n\n#{t('exercises.editor.timeout', permitted_execution_time: submission.exercise.execution_environment.permitted_execution_time.to_s)}" end end diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 3b06f877..cfd83fda 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -453,7 +453,7 @@ class DockerClient Timeout.timeout(@execution_environment.permitted_execution_time.to_i) do # TODO: check phusion doku again if we need -i -t options here # https://stackoverflow.com/questions/363223/how-do-i-get-both-stdout-and-stderr-to-go-to-the-terminal-and-a-log-file - output = container.exec(['bash', '-c', "#{command} 1> >(tee -a /tmp/stdout.log) 2> >(tee -a /tmp/stderr.log >&2); rm /tmp/std*.log"], tty: false) + output = container.exec(['bash', '-c', "#{command} 1> >(tee -a /tmp/stdout.log) 2> >(tee -a /tmp/stderr.log >&2); rm -f /tmp/std*.log"], tty: false) end Rails.logger.debug 'output from container.exec' Rails.logger.debug output