From 898074be3f0a67fbf0bf113df97b0ad2c6fafe6d Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 26 Jan 2016 14:26:18 +0100 Subject: [PATCH 01/29] Added render command, outputs the content in a div. --- app/assets/javascripts/editor.js.erb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb index b5eefbf5..2da4a37b 100644 --- a/app/assets/javascripts/editor.js.erb +++ b/app/assets/javascripts/editor.js.erb @@ -30,7 +30,7 @@ $(function() { numMessages = 0, turtlecanvas = $('#turtlecanvas'), prompt = $('#prompt'), - commands = ['input', 'write', 'turtle', 'turtlebatch', 'exit', 'timeout', 'status'], + commands = ['input', 'write', 'turtle', 'turtlebatch', 'render', 'exit', 'timeout', 'status'], streams = ['stdin', 'stdout', 'stderr']; var ENTER_KEY_CODE = 13; @@ -245,6 +245,18 @@ $(function() { } }; + var findOrCreateRenderElement = function(index) { + if ($('#render-' + index).isPresent()) { + return $('#render-' + index); + } else { + var element = $('
').attr('id', 'render-' + index); + $('#render').append(element); + return element; + } + }; + + + var getPanelClass = function(result) { if (result.stderr && !result.score) { return 'panel-danger'; @@ -1172,6 +1184,9 @@ $(function() { showCanvas(); handleTurtlebatchCommand(msg); break; + case 'render': + renderWebsocketOutput(msg); + break; case 'exit': killWebsocketAndContainer(); break; @@ -1185,6 +1200,11 @@ $(function() { } }; + var renderWebsocketOutput = function(msg){ + var element = findOrCreateRenderElement(0); + element.append(msg.data); + }; + var printWebsocketOutput = function(msg) { if (!msg.data) { return; From ecad5b80fa973b6c48673c9bb74e0c2a603a7934 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 27 Jan 2016 10:16:13 +0100 Subject: [PATCH 02/29] re-enable data submission via shared folders. --- lib/docker_client.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/docker_client.rb b/lib/docker_client.rb index fc760981..7b6007f9 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -21,14 +21,14 @@ class DockerClient end def self.clean_container_workspace(container) - container.exec(['bash', '-c', 'rm -rf ' + CONTAINER_WORKSPACE_PATH + '/*']) -=begin + # remove files when using transferral via Docker API archive_in (transmit) + #container.exec(['bash', '-c', 'rm -rf ' + CONTAINER_WORKSPACE_PATH + '/*']) + local_workspace_path = local_workspace_path(container) if local_workspace_path && Pathname.new(local_workspace_path).exist? Pathname.new(local_workspace_path).children.each{ |p| p.rmtree} #FileUtils.rmdir(Pathname.new(local_workspace_path)) end -=end end def command_substitutions(filename) @@ -295,7 +295,7 @@ class DockerClient Run commands by attaching a websocket to Docker. """ command = submission.execution_environment.run_command % command_substitutions(filename) - create_workspace_files = proc { create_workspace_files_transmit(container, submission) } + create_workspace_files = proc { create_workspace_files(container, submission) } execute_websocket_command(command, create_workspace_files, block) end @@ -304,7 +304,7 @@ class DockerClient Stick to existing Docker API with exec command. """ command = submission.execution_environment.test_command % command_substitutions(filename) - create_workspace_files = proc { create_workspace_files_transmit(container, submission) } + create_workspace_files = proc { create_workspace_files(container, submission) } execute_command(command, create_workspace_files, block) end From 61426e8f2eaf7a359b03a4eb9ebb38e650ec39a3 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 27 Jan 2016 15:49:38 +0100 Subject: [PATCH 03/29] uncomment some logging, and recreate folder for local workspace path in the docker client. --- lib/docker_client.rb | 2 +- lib/docker_container_pool.rb | 10 +++++----- lib/xikolo/client.rb | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 7b6007f9..f1d855ac 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -98,7 +98,7 @@ class DockerClient container = Docker::Container.create(container_creation_options(execution_environment)) local_workspace_path = generate_local_workspace_path # container.start always creates the passed local_workspace_path on disk. Seems like we have to live with that, therefore we can also just create the empty folder ourselves. - # FileUtils.mkdir(local_workspace_path) + FileUtils.mkdir(local_workspace_path) container.start(container_start_options(execution_environment, local_workspace_path)) container.start_time = Time.now container.status = :created diff --git a/lib/docker_container_pool.rb b/lib/docker_container_pool.rb index 90357875..1921afdb 100644 --- a/lib/docker_container_pool.rb +++ b/lib/docker_container_pool.rb @@ -41,7 +41,7 @@ class DockerContainerPool @all_containers[execution_environment.id]+=[container] if(!@containers[execution_environment.id].include?(container)) @containers[execution_environment.id]+=[container] - Rails.logger.debug('Added container ' + container.to_s + ' to all_pool for execution environment ' + execution_environment.to_s + '. Containers in all_pool: ' + @all_containers[execution_environment.id].size.to_s) + #Rails.logger.debug('Added container ' + container.to_s + ' to all_pool for execution environment ' + execution_environment.to_s + '. Containers in all_pool: ' + @all_containers[execution_environment.id].size.to_s) else Rails.logger.info('failed trying to add existing container ' + container.to_s + ' to execution_environment ' + execution_environment.to_s) end @@ -50,7 +50,7 @@ class DockerContainerPool def self.create_container(execution_environment) container = DockerClient.create_container(execution_environment) container.status = 'available' - Rails.logger.debug('created container ' + container.to_s + ' for execution environment ' + execution_environment.to_s) + #Rails.logger.debug('created container ' + container.to_s + ' for execution environment ' + execution_environment.to_s) container end @@ -120,11 +120,11 @@ class DockerContainerPool if refill_count > 0 Rails.logger.info('Adding ' + refill_count.to_s + ' containers for execution_environment ' + execution_environment.name ) c = refill_count.times.map { create_container(execution_environment) } - Rails.logger.info('Created containers: ' + c.to_s ) + #Rails.logger.info('Created containers: ' + c.to_s ) @containers[execution_environment.id] += c @all_containers[execution_environment.id] += c - Rails.logger.debug('@containers for ' + execution_environment.name.to_s + ' (' + @containers.object_id.to_s + ') has the following content: '+ @containers[execution_environment.id].to_s) - Rails.logger.debug('@all_containers for ' + execution_environment.name.to_s + ' (' + @all_containers.object_id.to_s + ') has the following content: ' + @all_containers[execution_environment.id].to_s) + #Rails.logger.debug('@containers for ' + execution_environment.name.to_s + ' (' + @containers.object_id.to_s + ') has the following content: '+ @containers[execution_environment.id].to_s) + #Rails.logger.debug('@all_containers for ' + execution_environment.name.to_s + ' (' + @all_containers.object_id.to_s + ') has the following content: ' + @all_containers[execution_environment.id].to_s) end end diff --git a/lib/xikolo/client.rb b/lib/xikolo/client.rb index db48c91a..ecad50e7 100644 --- a/lib/xikolo/client.rb +++ b/lib/xikolo/client.rb @@ -34,6 +34,7 @@ class Xikolo::Client end def self.url + #todo: JanR: set an environment variable here, fallback value: http://open.hpi.de/api/ 'http://localhost:2000/api/' end From de846389793e7a513cfbd6fa980e39e42e713177 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 27 Jan 2016 16:42:25 +0100 Subject: [PATCH 04/29] Try to re-combine websocket message chunks containing an image tag. --- app/controllers/submissions_controller.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 3aa3adf4..5bac07c4 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -176,7 +176,24 @@ class SubmissionsController < ApplicationController for part in message.split("\n") self.parse_message(part,output_stream,socket,false) end + elsif(message.include? "")) + @buffer += message + parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>@buffer} + socket.send_data JSON.dump(parsed) + #socket.send_data @buffer + @buffering = false + #Rails.logger.info('Sent complete buffer') + elsif(@buffering) + @buffer += message + #Rails.logger.info('Appending to buffer') else + #Rails.logger.info('else') parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>message} socket.send_data JSON.dump(parsed) Rails.logger.info('parse_message sent: ' + JSON.dump(parsed)) From aa8870b8c85e2edcf67148cecb551e40611cb9e7 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 09:28:50 +0100 Subject: [PATCH 05/29] Add endpoint for import (leoselig/codeocean#1) - currently route is still named /thin_common_cartridge - points to exercise controller for simplicity (open for discussion) --- app/controllers/exercises_controller.rb | 10 ++++++++++ config/routes.rb | 2 ++ 2 files changed, 12 insertions(+) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 4f5e5b81..ec675de9 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -11,6 +11,10 @@ class ExercisesController < ApplicationController before_action :set_file_types, only: [:create, :edit, :new, :update] before_action :set_teams, only: [:create, :edit, :new, :update] + skip_before_filter :verify_authenticity_token, only: [:import_thin_common_cartridge] + skip_after_action :verify_authorized, only: [:import_thin_common_cartridge] + skip_after_action :verify_policy_scoped, only: [:import_thin_common_cartridge] + def authorize! authorize(@exercise || @exercises) end @@ -62,6 +66,12 @@ class ExercisesController < ApplicationController def edit end + def import_thin_common_cartridge + logger.info(request.headers['Authorization']) + logger.info(request.headers['Authorisation']) + render :nothing => true, :status => 200, :content_type => 'text/html' + end + def exercise_params params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :hide_file_tree, :team_id, :title, files_attributes: file_attributes).merge(user_id: current_user.id, user_type: current_user.class.name) end diff --git a/config/routes.rb b/config/routes.rb index 24f6a0d9..af5dfdaa 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,6 +40,8 @@ Rails.application.routes.draw do resources :hints end + post '/thin_common_cartridge' => 'exercises#import_thin_common_cartridge' + resources :exercises do collection do match '', to: 'exercises#batch_update', via: [:patch, :put] From b5b8b3ab6811fb0684a83ea692e46cbba36dcbf0 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 10:25:54 +0100 Subject: [PATCH 06/29] Add CodeHarborLink controller (leoselig/codeocean#2) --- app/assets/javascripts/code_harbor_link.js.coffee | 3 +++ app/assets/stylesheets/code_harbor_link.css.scss | 3 +++ app/controllers/code_harbor_link_controller.rb | 2 ++ app/helpers/code_harbor_link_helper.rb | 2 ++ 4 files changed, 10 insertions(+) create mode 100644 app/assets/javascripts/code_harbor_link.js.coffee create mode 100644 app/assets/stylesheets/code_harbor_link.css.scss create mode 100644 app/controllers/code_harbor_link_controller.rb create mode 100644 app/helpers/code_harbor_link_helper.rb diff --git a/app/assets/javascripts/code_harbor_link.js.coffee b/app/assets/javascripts/code_harbor_link.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/code_harbor_link.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/code_harbor_link.css.scss b/app/assets/stylesheets/code_harbor_link.css.scss new file mode 100644 index 00000000..3c615ada --- /dev/null +++ b/app/assets/stylesheets/code_harbor_link.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the CodeHarborLink controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/code_harbor_link_controller.rb b/app/controllers/code_harbor_link_controller.rb new file mode 100644 index 00000000..a551e9b1 --- /dev/null +++ b/app/controllers/code_harbor_link_controller.rb @@ -0,0 +1,2 @@ +class CodeHarborLinkController < ApplicationController +end diff --git a/app/helpers/code_harbor_link_helper.rb b/app/helpers/code_harbor_link_helper.rb new file mode 100644 index 00000000..f1c55f9d --- /dev/null +++ b/app/helpers/code_harbor_link_helper.rb @@ -0,0 +1,2 @@ +module CodeHarborLinkHelper +end From 92f6c7a06f8d959c405228b2f15ae2dd8902160e Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 10:58:54 +0100 Subject: [PATCH 07/29] Revert "Add CodeHarborLink controller" This reverts commit b5b8b3ab6811fb0684a83ea692e46cbba36dcbf0. - next commit will do a complete scaffold (leoselig/codeocean#2) --- app/assets/javascripts/code_harbor_link.js.coffee | 3 --- app/assets/stylesheets/code_harbor_link.css.scss | 3 --- app/controllers/code_harbor_link_controller.rb | 2 -- app/helpers/code_harbor_link_helper.rb | 2 -- 4 files changed, 10 deletions(-) delete mode 100644 app/assets/javascripts/code_harbor_link.js.coffee delete mode 100644 app/assets/stylesheets/code_harbor_link.css.scss delete mode 100644 app/controllers/code_harbor_link_controller.rb delete mode 100644 app/helpers/code_harbor_link_helper.rb diff --git a/app/assets/javascripts/code_harbor_link.js.coffee b/app/assets/javascripts/code_harbor_link.js.coffee deleted file mode 100644 index 24f83d18..00000000 --- a/app/assets/javascripts/code_harbor_link.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/code_harbor_link.css.scss b/app/assets/stylesheets/code_harbor_link.css.scss deleted file mode 100644 index 3c615ada..00000000 --- a/app/assets/stylesheets/code_harbor_link.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the CodeHarborLink controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/code_harbor_link_controller.rb b/app/controllers/code_harbor_link_controller.rb deleted file mode 100644 index a551e9b1..00000000 --- a/app/controllers/code_harbor_link_controller.rb +++ /dev/null @@ -1,2 +0,0 @@ -class CodeHarborLinkController < ApplicationController -end diff --git a/app/helpers/code_harbor_link_helper.rb b/app/helpers/code_harbor_link_helper.rb deleted file mode 100644 index f1c55f9d..00000000 --- a/app/helpers/code_harbor_link_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module CodeHarborLinkHelper -end From 76bf3dd3f0ef18973f37e9da3ec9f45cc1c76c3a Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 10:59:49 +0100 Subject: [PATCH 08/29] Scaffold CodeHarbourLink with field oauth2token (leoselig/codeocean#2) --- .../javascripts/code_harbor_links.js.coffee | 3 + .../stylesheets/code_harbor_links.css.scss | 3 + app/assets/stylesheets/scaffolds.css.scss | 69 +++++++++++++++++ .../code_harbor_links_controller.rb | 74 +++++++++++++++++++ app/helpers/code_harbor_links_helper.rb | 2 + app/models/code_harbor_link.rb | 2 + app/views/code_harbor_links/_form.html.erb | 21 ++++++ app/views/code_harbor_links/edit.html.erb | 6 ++ app/views/code_harbor_links/index.html.erb | 25 +++++++ .../code_harbor_links/index.json.jbuilder | 4 + app/views/code_harbor_links/new.html.erb | 5 ++ app/views/code_harbor_links/show.html.erb | 9 +++ .../code_harbor_links/show.json.jbuilder | 1 + config/routes.rb | 1 + ...20160204094409_create_code_harbor_links.rb | 9 +++ 15 files changed, 234 insertions(+) create mode 100644 app/assets/javascripts/code_harbor_links.js.coffee create mode 100644 app/assets/stylesheets/code_harbor_links.css.scss create mode 100644 app/assets/stylesheets/scaffolds.css.scss create mode 100644 app/controllers/code_harbor_links_controller.rb create mode 100644 app/helpers/code_harbor_links_helper.rb create mode 100644 app/models/code_harbor_link.rb create mode 100644 app/views/code_harbor_links/_form.html.erb create mode 100644 app/views/code_harbor_links/edit.html.erb create mode 100644 app/views/code_harbor_links/index.html.erb create mode 100644 app/views/code_harbor_links/index.json.jbuilder create mode 100644 app/views/code_harbor_links/new.html.erb create mode 100644 app/views/code_harbor_links/show.html.erb create mode 100644 app/views/code_harbor_links/show.json.jbuilder create mode 100644 db/migrate/20160204094409_create_code_harbor_links.rb diff --git a/app/assets/javascripts/code_harbor_links.js.coffee b/app/assets/javascripts/code_harbor_links.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/code_harbor_links.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/code_harbor_links.css.scss b/app/assets/stylesheets/code_harbor_links.css.scss new file mode 100644 index 00000000..5ca7b3ce --- /dev/null +++ b/app/assets/stylesheets/code_harbor_links.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the CodeHarborLinks controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/scaffolds.css.scss b/app/assets/stylesheets/scaffolds.css.scss new file mode 100644 index 00000000..6ec6a8ff --- /dev/null +++ b/app/assets/stylesheets/scaffolds.css.scss @@ -0,0 +1,69 @@ +body { + background-color: #fff; + color: #333; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; + &:visited { + color: #666; + } + &:hover { + color: #fff; + background-color: #000; + } +} + +div { + &.field, &.actions { + margin-bottom: 10px; + } +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; + } + ul li { + font-size: 12px; + list-style: square; + } +} diff --git a/app/controllers/code_harbor_links_controller.rb b/app/controllers/code_harbor_links_controller.rb new file mode 100644 index 00000000..849af648 --- /dev/null +++ b/app/controllers/code_harbor_links_controller.rb @@ -0,0 +1,74 @@ +class CodeHarborLinksController < ApplicationController + before_action :set_code_harbor_link, only: [:show, :edit, :update, :destroy] + + # GET /code_harbor_links + # GET /code_harbor_links.json + def index + @code_harbor_links = CodeHarborLink.all + end + + # GET /code_harbor_links/1 + # GET /code_harbor_links/1.json + def show + end + + # GET /code_harbor_links/new + def new + @code_harbor_link = CodeHarborLink.new + end + + # GET /code_harbor_links/1/edit + def edit + end + + # POST /code_harbor_links + # POST /code_harbor_links.json + def create + @code_harbor_link = CodeHarborLink.new(code_harbor_link_params) + + respond_to do |format| + if @code_harbor_link.save + format.html { redirect_to @code_harbor_link, notice: 'Code harbor link was successfully created.' } + format.json { render :show, status: :created, location: @code_harbor_link } + else + format.html { render :new } + format.json { render json: @code_harbor_link.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /code_harbor_links/1 + # PATCH/PUT /code_harbor_links/1.json + def update + respond_to do |format| + if @code_harbor_link.update(code_harbor_link_params) + format.html { redirect_to @code_harbor_link, notice: 'Code harbor link was successfully updated.' } + format.json { render :show, status: :ok, location: @code_harbor_link } + else + format.html { render :edit } + format.json { render json: @code_harbor_link.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /code_harbor_links/1 + # DELETE /code_harbor_links/1.json + def destroy + @code_harbor_link.destroy + respond_to do |format| + format.html { redirect_to code_harbor_links_url, notice: 'Code harbor link was successfully destroyed.' } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_code_harbor_link + @code_harbor_link = CodeHarborLink.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def code_harbor_link_params + params.require(:code_harbor_link).permit(:oauth2token) + end +end diff --git a/app/helpers/code_harbor_links_helper.rb b/app/helpers/code_harbor_links_helper.rb new file mode 100644 index 00000000..d8e92ddf --- /dev/null +++ b/app/helpers/code_harbor_links_helper.rb @@ -0,0 +1,2 @@ +module CodeHarborLinksHelper +end diff --git a/app/models/code_harbor_link.rb b/app/models/code_harbor_link.rb new file mode 100644 index 00000000..d5012e11 --- /dev/null +++ b/app/models/code_harbor_link.rb @@ -0,0 +1,2 @@ +class CodeHarborLink < ActiveRecord::Base +end diff --git a/app/views/code_harbor_links/_form.html.erb b/app/views/code_harbor_links/_form.html.erb new file mode 100644 index 00000000..b4c5b2ab --- /dev/null +++ b/app/views/code_harbor_links/_form.html.erb @@ -0,0 +1,21 @@ +<%= form_for(@code_harbor_link) do |f| %> + <% if @code_harbor_link.errors.any? %> +
+

<%= pluralize(@code_harbor_link.errors.count, "error") %> prohibited this code_harbor_link from being saved:

+ +
    + <% @code_harbor_link.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= f.label :oauth2token %>
+ <%= f.text_field :oauth2token %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/code_harbor_links/edit.html.erb b/app/views/code_harbor_links/edit.html.erb new file mode 100644 index 00000000..f75f360d --- /dev/null +++ b/app/views/code_harbor_links/edit.html.erb @@ -0,0 +1,6 @@ +

Editing code_harbor_link

+ +<%= render 'form' %> + +<%= link_to 'Show', @code_harbor_link %> | +<%= link_to 'Back', code_harbor_links_path %> diff --git a/app/views/code_harbor_links/index.html.erb b/app/views/code_harbor_links/index.html.erb new file mode 100644 index 00000000..0069df36 --- /dev/null +++ b/app/views/code_harbor_links/index.html.erb @@ -0,0 +1,25 @@ +

Listing code_harbor_links

+ + + + + + + + + + + <% @code_harbor_links.each do |code_harbor_link| %> + + + + + + + <% end %> + +
Oauth2token
<%= code_harbor_link.oauth2token %><%= link_to 'Show', code_harbor_link %><%= link_to 'Edit', edit_code_harbor_link_path(code_harbor_link) %><%= link_to 'Destroy', code_harbor_link, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Code harbor link', new_code_harbor_link_path %> diff --git a/app/views/code_harbor_links/index.json.jbuilder b/app/views/code_harbor_links/index.json.jbuilder new file mode 100644 index 00000000..defff8f3 --- /dev/null +++ b/app/views/code_harbor_links/index.json.jbuilder @@ -0,0 +1,4 @@ +json.array!(@code_harbor_links) do |code_harbor_link| + json.extract! code_harbor_link, :id, :oauth2token + json.url code_harbor_link_url(code_harbor_link, format: :json) +end diff --git a/app/views/code_harbor_links/new.html.erb b/app/views/code_harbor_links/new.html.erb new file mode 100644 index 00000000..0ba6ae61 --- /dev/null +++ b/app/views/code_harbor_links/new.html.erb @@ -0,0 +1,5 @@ +

New code_harbor_link

+ +<%= render 'form' %> + +<%= link_to 'Back', code_harbor_links_path %> diff --git a/app/views/code_harbor_links/show.html.erb b/app/views/code_harbor_links/show.html.erb new file mode 100644 index 00000000..4bad1a5e --- /dev/null +++ b/app/views/code_harbor_links/show.html.erb @@ -0,0 +1,9 @@ +

<%= notice %>

+ +

+ Oauth2token: + <%= @code_harbor_link.oauth2token %> +

+ +<%= link_to 'Edit', edit_code_harbor_link_path(@code_harbor_link) %> | +<%= link_to 'Back', code_harbor_links_path %> diff --git a/app/views/code_harbor_links/show.json.jbuilder b/app/views/code_harbor_links/show.json.jbuilder new file mode 100644 index 00000000..b8a1e789 --- /dev/null +++ b/app/views/code_harbor_links/show.json.jbuilder @@ -0,0 +1 @@ +json.extract! @code_harbor_link, :id, :oauth2token, :created_at, :updated_at diff --git a/config/routes.rb b/config/routes.rb index 24f6a0d9..4b9c5dc2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ FILENAME_REGEXP = /[\w\.]+/ unless Kernel.const_defined?(:FILENAME_REGEXP) Rails.application.routes.draw do + resources :code_harbor_links resources :request_for_comments get '/my_request_for_comments', as: 'my_request_for_comments', to: 'request_for_comments#get_my_comment_requests' resources :comments, except: [:destroy] do diff --git a/db/migrate/20160204094409_create_code_harbor_links.rb b/db/migrate/20160204094409_create_code_harbor_links.rb new file mode 100644 index 00000000..b87d5c9d --- /dev/null +++ b/db/migrate/20160204094409_create_code_harbor_links.rb @@ -0,0 +1,9 @@ +class CreateCodeHarborLinks < ActiveRecord::Migration + def change + create_table :code_harbor_links do |t| + t.string :oauth2token + + t.timestamps + end + end +end From e534a8cb2d1f81df3adfa11c7a0de452b09fcc83 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 11:34:54 +0100 Subject: [PATCH 09/29] Add authorization to CodeHarborLink controller (leoselig/codeocean#2) --- .../code_harbor_links_controller.rb | 40 ++++++++----------- app/policies/code_harbor_link_policy.rb | 3 ++ db/schema.rb | 8 +++- 3 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 app/policies/code_harbor_link_policy.rb diff --git a/app/controllers/code_harbor_links_controller.rb b/app/controllers/code_harbor_links_controller.rb index 849af648..71e19d43 100644 --- a/app/controllers/code_harbor_links_controller.rb +++ b/app/controllers/code_harbor_links_controller.rb @@ -1,70 +1,62 @@ class CodeHarborLinksController < ApplicationController + include CommonBehavior before_action :set_code_harbor_link, only: [:show, :edit, :update, :destroy] + def authorize! + authorize(@code_harbor_link || @code_harbor_links) + end + private :authorize! + # GET /code_harbor_links # GET /code_harbor_links.json def index @code_harbor_links = CodeHarborLink.all + authorize! end # GET /code_harbor_links/1 # GET /code_harbor_links/1.json def show + authorize! end # GET /code_harbor_links/new def new @code_harbor_link = CodeHarborLink.new + authorize! end # GET /code_harbor_links/1/edit def edit + authorize! end # POST /code_harbor_links # POST /code_harbor_links.json def create @code_harbor_link = CodeHarborLink.new(code_harbor_link_params) - - respond_to do |format| - if @code_harbor_link.save - format.html { redirect_to @code_harbor_link, notice: 'Code harbor link was successfully created.' } - format.json { render :show, status: :created, location: @code_harbor_link } - else - format.html { render :new } - format.json { render json: @code_harbor_link.errors, status: :unprocessable_entity } - end - end + authorize! + create_and_respond(object: @code_harbor_link) end # PATCH/PUT /code_harbor_links/1 # PATCH/PUT /code_harbor_links/1.json def update - respond_to do |format| - if @code_harbor_link.update(code_harbor_link_params) - format.html { redirect_to @code_harbor_link, notice: 'Code harbor link was successfully updated.' } - format.json { render :show, status: :ok, location: @code_harbor_link } - else - format.html { render :edit } - format.json { render json: @code_harbor_link.errors, status: :unprocessable_entity } - end - end + update_and_respond(object: @code_harbor_link, params: code_harbor_link_params) + authorize! end # DELETE /code_harbor_links/1 # DELETE /code_harbor_links/1.json def destroy - @code_harbor_link.destroy - respond_to do |format| - format.html { redirect_to code_harbor_links_url, notice: 'Code harbor link was successfully destroyed.' } - format.json { head :no_content } - end + destroy_and_respond(object: @code_harbor_link) end private # Use callbacks to share common setup or constraints between actions. def set_code_harbor_link @code_harbor_link = CodeHarborLink.find(params[:id]) + authorize! end # Never trust parameters from the scary internet, only allow the white list through. diff --git a/app/policies/code_harbor_link_policy.rb b/app/policies/code_harbor_link_policy.rb new file mode 100644 index 00000000..8726c22a --- /dev/null +++ b/app/policies/code_harbor_link_policy.rb @@ -0,0 +1,3 @@ +class CodeHarborLinkPolicy < AdminOnlyPolicy + +end diff --git a/db/schema.rb b/db/schema.rb index d895da3f..33456e7e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,11 +11,17 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150922125415) do +ActiveRecord::Schema.define(version: 20160204094409) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "code_harbor_links", force: true do |t| + t.string "oauth2token" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "comments", force: true do |t| t.integer "user_id" t.integer "file_id" From c947bbf15203453e467b7b7de207dcadf3b15d32 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 11:43:27 +0100 Subject: [PATCH 10/29] Add CodeHarbor links to administation navigation (leoselig/codeocean#2) --- app/views/application/_navigation.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/application/_navigation.html.slim b/app/views/application/_navigation.html.slim index 276723bf..4ab39e30 100644 --- a/app/views/application/_navigation.html.slim +++ b/app/views/application/_navigation.html.slim @@ -8,7 +8,7 @@ - if current_user.admin? li = link_to(t('breadcrumbs.dashboard.show'), admin_dashboard_path) li.divider - - models = [ExecutionEnvironment, Exercise, Consumer, ExternalUser, FileType, InternalUser, Submission, Team].sort_by { |model| model.model_name.human(count: 2) } + - models = [ExecutionEnvironment, Exercise, Consumer, CodeHarborLink, ExternalUser, FileType, InternalUser, Submission, Team].sort_by { |model| model.model_name.human(count: 2) } - models.each do |model| - if policy(model).index? li = link_to(model.model_name.human(count: 2), send(:"#{model.model_name.collection}_path")) From 057b19cf2aca676becc558379c3185c7ba92173f Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 11:47:44 +0100 Subject: [PATCH 11/29] Translate CodeHarbor links (en/de) - model name (singular/plural) - attribute oauth2token (leoselig/codeocean#2) --- config/locales/de.yml | 5 +++++ config/locales/en.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/config/locales/de.yml b/config/locales/de.yml index 9fd2dce0..66355194 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1,6 +1,8 @@ de: activerecord: attributes: + code_harbor_link: + oauth2token: OAuth2 Token consumer: name: Name oauth_key: OAuth Key @@ -90,6 +92,9 @@ de: internal_user_ids: Mitglieder name: Name models: + code_harbor_link: + one: CodeHarbor-Verknüpfung + other: CodeHarbor-Verknüpfungen consumer: one: Konsument other: Konsumenten diff --git a/config/locales/en.yml b/config/locales/en.yml index f005eea2..56fd4fc8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,6 +1,8 @@ en: activerecord: attributes: + code_harbor_link: + oauth2token: OAuth2 Token consumer: name: Name oauth_key: OAuth Key @@ -90,6 +92,9 @@ en: internal_user_ids: Members name: Name models: + code_harbor_link: + one: CodeHarbor Link + other: CodeHarbor Links consumer: one: Consumer other: Consumers From f2a1a748d5378dd25ac324b9d28b1ac349747ef9 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 12:05:57 +0100 Subject: [PATCH 12/29] Replace CodeHarbourLink .erb wtih .slim templates - this is consistent with the remaining view architecture (leoselig/codeocean#2) --- .../code_harbor_links_controller.rb | 2 +- app/models/code_harbor_link.rb | 6 +++++ app/views/code_harbor_links/_form.html.erb | 21 ---------------- app/views/code_harbor_links/_form.html.slim | 6 +++++ app/views/code_harbor_links/edit.html.erb | 6 ----- app/views/code_harbor_links/edit.html.slim | 3 +++ app/views/code_harbor_links/index.html.erb | 25 ------------------- app/views/code_harbor_links/index.html.slim | 18 +++++++++++++ .../code_harbor_links/index.json.jbuilder | 4 --- app/views/code_harbor_links/new.html.erb | 5 ---- app/views/code_harbor_links/new.html.slim | 3 +++ app/views/code_harbor_links/show.html.erb | 9 ------- app/views/code_harbor_links/show.html.slim | 7 ++++++ .../code_harbor_links/show.json.jbuilder | 1 - 14 files changed, 44 insertions(+), 72 deletions(-) delete mode 100644 app/views/code_harbor_links/_form.html.erb create mode 100644 app/views/code_harbor_links/_form.html.slim delete mode 100644 app/views/code_harbor_links/edit.html.erb create mode 100644 app/views/code_harbor_links/edit.html.slim delete mode 100644 app/views/code_harbor_links/index.html.erb create mode 100644 app/views/code_harbor_links/index.html.slim delete mode 100644 app/views/code_harbor_links/index.json.jbuilder delete mode 100644 app/views/code_harbor_links/new.html.erb create mode 100644 app/views/code_harbor_links/new.html.slim delete mode 100644 app/views/code_harbor_links/show.html.erb create mode 100644 app/views/code_harbor_links/show.html.slim delete mode 100644 app/views/code_harbor_links/show.json.jbuilder diff --git a/app/controllers/code_harbor_links_controller.rb b/app/controllers/code_harbor_links_controller.rb index 71e19d43..3b71a050 100644 --- a/app/controllers/code_harbor_links_controller.rb +++ b/app/controllers/code_harbor_links_controller.rb @@ -10,7 +10,7 @@ class CodeHarborLinksController < ApplicationController # GET /code_harbor_links # GET /code_harbor_links.json def index - @code_harbor_links = CodeHarborLink.all + @code_harbor_links = CodeHarborLink.paginate(page: params[:page]) authorize! end diff --git a/app/models/code_harbor_link.rb b/app/models/code_harbor_link.rb index d5012e11..ea91ab71 100644 --- a/app/models/code_harbor_link.rb +++ b/app/models/code_harbor_link.rb @@ -1,2 +1,8 @@ class CodeHarborLink < ActiveRecord::Base + validates :oauth2token, presence: true + + def to_s + oauth2token + end + end diff --git a/app/views/code_harbor_links/_form.html.erb b/app/views/code_harbor_links/_form.html.erb deleted file mode 100644 index b4c5b2ab..00000000 --- a/app/views/code_harbor_links/_form.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -<%= form_for(@code_harbor_link) do |f| %> - <% if @code_harbor_link.errors.any? %> -
-

<%= pluralize(@code_harbor_link.errors.count, "error") %> prohibited this code_harbor_link from being saved:

- -
    - <% @code_harbor_link.errors.full_messages.each do |message| %> -
  • <%= message %>
  • - <% end %> -
-
- <% end %> - -
- <%= f.label :oauth2token %>
- <%= f.text_field :oauth2token %> -
-
- <%= f.submit %> -
-<% end %> diff --git a/app/views/code_harbor_links/_form.html.slim b/app/views/code_harbor_links/_form.html.slim new file mode 100644 index 00000000..f7b449ee --- /dev/null +++ b/app/views/code_harbor_links/_form.html.slim @@ -0,0 +1,6 @@ += form_for(@code_harbor_link) do |f| + = render('shared/form_errors', object: @code_harbor_link) + .form-group + = f.label(:oauth2token) + = f.text_field(:oauth2token, class: 'form-control', required: true) + .actions = render('shared/submit_button', f: f, object: @code_harbor_link) diff --git a/app/views/code_harbor_links/edit.html.erb b/app/views/code_harbor_links/edit.html.erb deleted file mode 100644 index f75f360d..00000000 --- a/app/views/code_harbor_links/edit.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -

Editing code_harbor_link

- -<%= render 'form' %> - -<%= link_to 'Show', @code_harbor_link %> | -<%= link_to 'Back', code_harbor_links_path %> diff --git a/app/views/code_harbor_links/edit.html.slim b/app/views/code_harbor_links/edit.html.slim new file mode 100644 index 00000000..d1c7ea8f --- /dev/null +++ b/app/views/code_harbor_links/edit.html.slim @@ -0,0 +1,3 @@ +h1 = @code_harbor_link + += render('form') diff --git a/app/views/code_harbor_links/index.html.erb b/app/views/code_harbor_links/index.html.erb deleted file mode 100644 index 0069df36..00000000 --- a/app/views/code_harbor_links/index.html.erb +++ /dev/null @@ -1,25 +0,0 @@ -

Listing code_harbor_links

- - - - - - - - - - - <% @code_harbor_links.each do |code_harbor_link| %> - - - - - - - <% end %> - -
Oauth2token
<%= code_harbor_link.oauth2token %><%= link_to 'Show', code_harbor_link %><%= link_to 'Edit', edit_code_harbor_link_path(code_harbor_link) %><%= link_to 'Destroy', code_harbor_link, method: :delete, data: { confirm: 'Are you sure?' } %>
- -
- -<%= link_to 'New Code harbor link', new_code_harbor_link_path %> diff --git a/app/views/code_harbor_links/index.html.slim b/app/views/code_harbor_links/index.html.slim new file mode 100644 index 00000000..953985c4 --- /dev/null +++ b/app/views/code_harbor_links/index.html.slim @@ -0,0 +1,18 @@ +h1 = CodeHarborLink.model_name.human(count: 2) + +.table-responsive + table.table + thead + tr + th = t('activerecord.attributes.code_harbor_link.oauth2token') + th colspan=3 = t('shared.actions') + tbody + - @code_harbor_links.each do |code_harbor_link| + tr + td = code_harbor_link.oauth2token + td = link_to(t('shared.show'), code_harbor_link) + td = link_to(t('shared.edit'), edit_code_harbor_link_path(code_harbor_link)) + td = link_to(t('shared.destroy'), code_harbor_link, data: {confirm: t('shared.confirm_destroy')}, method: :delete) + += render('shared/pagination', collection: @code_harbor_links) +p = render('shared/new_button', model: CodeHarborLink) diff --git a/app/views/code_harbor_links/index.json.jbuilder b/app/views/code_harbor_links/index.json.jbuilder deleted file mode 100644 index defff8f3..00000000 --- a/app/views/code_harbor_links/index.json.jbuilder +++ /dev/null @@ -1,4 +0,0 @@ -json.array!(@code_harbor_links) do |code_harbor_link| - json.extract! code_harbor_link, :id, :oauth2token - json.url code_harbor_link_url(code_harbor_link, format: :json) -end diff --git a/app/views/code_harbor_links/new.html.erb b/app/views/code_harbor_links/new.html.erb deleted file mode 100644 index 0ba6ae61..00000000 --- a/app/views/code_harbor_links/new.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -

New code_harbor_link

- -<%= render 'form' %> - -<%= link_to 'Back', code_harbor_links_path %> diff --git a/app/views/code_harbor_links/new.html.slim b/app/views/code_harbor_links/new.html.slim new file mode 100644 index 00000000..ef19a3e6 --- /dev/null +++ b/app/views/code_harbor_links/new.html.slim @@ -0,0 +1,3 @@ +h1 = t('shared.new_model', model: CodeHarborLink.model_name.human) + += render('form') diff --git a/app/views/code_harbor_links/show.html.erb b/app/views/code_harbor_links/show.html.erb deleted file mode 100644 index 4bad1a5e..00000000 --- a/app/views/code_harbor_links/show.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -

<%= notice %>

- -

- Oauth2token: - <%= @code_harbor_link.oauth2token %> -

- -<%= link_to 'Edit', edit_code_harbor_link_path(@code_harbor_link) %> | -<%= link_to 'Back', code_harbor_links_path %> diff --git a/app/views/code_harbor_links/show.html.slim b/app/views/code_harbor_links/show.html.slim new file mode 100644 index 00000000..b2d95342 --- /dev/null +++ b/app/views/code_harbor_links/show.html.slim @@ -0,0 +1,7 @@ +h1 + = @code_harbor_link + = render('shared/edit_button', object: @code_harbor_link) if policy(@code_harbor_link).edit? + +- %w[oauth2token].each do |attribute| + = row(label: "code_harbor_link.#{attribute}") do + = content_tag(:input, nil, class: 'form-control', readonly: true, value: @code_harbor_link.send(attribute)) diff --git a/app/views/code_harbor_links/show.json.jbuilder b/app/views/code_harbor_links/show.json.jbuilder deleted file mode 100644 index b8a1e789..00000000 --- a/app/views/code_harbor_links/show.json.jbuilder +++ /dev/null @@ -1 +0,0 @@ -json.extract! @code_harbor_link, :id, :oauth2token, :created_at, :updated_at From 68e74a9d85d55a75e476d04756969a8a0e20a667 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 12:38:46 +0100 Subject: [PATCH 13/29] Add association User has many CodeHarborLink - add migration tht associates User with CodeHarborLink - add belongs_to from CodeHarborLink to User - changed CodeHarborLinkController#index to only serve current user's CodeHarborLinks (leoselig/codeocean#2) --- app/controllers/code_harbor_links_controller.rb | 3 ++- app/models/code_harbor_link.rb | 3 +++ db/migrate/20160204111716_add_user_to_code_harbor_link.rb | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20160204111716_add_user_to_code_harbor_link.rb diff --git a/app/controllers/code_harbor_links_controller.rb b/app/controllers/code_harbor_links_controller.rb index 3b71a050..4763976b 100644 --- a/app/controllers/code_harbor_links_controller.rb +++ b/app/controllers/code_harbor_links_controller.rb @@ -10,7 +10,7 @@ class CodeHarborLinksController < ApplicationController # GET /code_harbor_links # GET /code_harbor_links.json def index - @code_harbor_links = CodeHarborLink.paginate(page: params[:page]) + @code_harbor_links = CodeHarborLink.where(user_id: current_user.id).paginate(page: params[:page]) authorize! end @@ -56,6 +56,7 @@ class CodeHarborLinksController < ApplicationController # Use callbacks to share common setup or constraints between actions. def set_code_harbor_link @code_harbor_link = CodeHarborLink.find(params[:id]) + @code_harbor_link.user = current_user authorize! end diff --git a/app/models/code_harbor_link.rb b/app/models/code_harbor_link.rb index ea91ab71..54250644 100644 --- a/app/models/code_harbor_link.rb +++ b/app/models/code_harbor_link.rb @@ -1,5 +1,8 @@ class CodeHarborLink < ActiveRecord::Base validates :oauth2token, presence: true + validates :user_id, presence: true + + belongs_to :user def to_s oauth2token diff --git a/db/migrate/20160204111716_add_user_to_code_harbor_link.rb b/db/migrate/20160204111716_add_user_to_code_harbor_link.rb new file mode 100644 index 00000000..8fa36ed1 --- /dev/null +++ b/db/migrate/20160204111716_add_user_to_code_harbor_link.rb @@ -0,0 +1,5 @@ +class AddUserToCodeHarborLink < ActiveRecord::Migration + def change + add_reference :code_harbor_links, :user, index: true, foreign_key: true + end +end From aee5585189d5dd8aa7640e30fe08ade39b29a812 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 13:32:50 +0100 Subject: [PATCH 14/29] =?UTF-8?q?Change=20German=20i18n=20"CodeHarbor-Verk?= =?UTF-8?q?n=C3=BCpfung(en)"=20to=20"...Link(s)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (leoselig/codeocean#2) --- config/locales/de.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/de.yml b/config/locales/de.yml index 66355194..01e1bf7c 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -93,8 +93,8 @@ de: name: Name models: code_harbor_link: - one: CodeHarbor-Verknüpfung - other: CodeHarbor-Verknüpfungen + one: CodeHarbor-Link + other: CodeHarbor-Links consumer: one: Konsument other: Konsumenten From c3df7ff482ac281fed8dbf5868d5addba079c184 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 13:34:18 +0100 Subject: [PATCH 15/29] Remove empty .coffee file - was scaffolded (leoselig/codeocean#2) --- app/assets/javascripts/code_harbor_links.js.coffee | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 app/assets/javascripts/code_harbor_links.js.coffee diff --git a/app/assets/javascripts/code_harbor_links.js.coffee b/app/assets/javascripts/code_harbor_links.js.coffee deleted file mode 100644 index 24f83d18..00000000 --- a/app/assets/javascripts/code_harbor_links.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://coffeescript.org/ From 63502831aa435fa4d16467a55114114e8b131c93 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 13:34:55 +0100 Subject: [PATCH 16/29] Change forgotten schema.rb (leoselig/codeocean#2) --- db/schema.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 33456e7e..793c021a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160204094409) do +ActiveRecord::Schema.define(version: 20160204111716) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -20,8 +20,11 @@ ActiveRecord::Schema.define(version: 20160204094409) do t.string "oauth2token" t.datetime "created_at" t.datetime "updated_at" + t.integer "user_id" end + add_index "code_harbor_links", ["user_id"], name: "index_code_harbor_links_on_user_id", using: :btree + create_table "comments", force: true do |t| t.integer "user_id" t.integer "file_id" From 5a190c0c792185d509d08badc6af41f6a4cd9be7 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Fri, 12 Feb 2016 10:57:44 +0100 Subject: [PATCH 17/29] Fix wrong belongs_to :user - because of polymorphic user model this didn't work - changed to :internal_user because that's anyway the only type of user we want to impoprt from (leoselig/codeocean#1) --- app/models/code_harbor_link.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/code_harbor_link.rb b/app/models/code_harbor_link.rb index 54250644..2e219aa9 100644 --- a/app/models/code_harbor_link.rb +++ b/app/models/code_harbor_link.rb @@ -2,7 +2,9 @@ class CodeHarborLink < ActiveRecord::Base validates :oauth2token, presence: true validates :user_id, presence: true - belongs_to :user + belongs_to :internal_user, foreign_key: :user_id + alias_method :user, :internal_user + alias_method :user=, :internal_user= def to_s oauth2token From 943355d9c7661bca892c44ca58d3ff1ed54e4e1c Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Fri, 12 Feb 2016 11:01:24 +0100 Subject: [PATCH 18/29] Add #from_proforma_xml to exercise (only meta data import) - method only considers title and description for now - sets up relation to execution environment with id 1, just to pass validation for now (leoselig/codeocean#1) --- Gemfile | 1 + Gemfile.lock | 1 + app/models/exercise.rb | 9 +++++++++ 3 files changed, 11 insertions(+) diff --git a/Gemfile b/Gemfile index e77ae876..5c6bbd31 100644 --- a/Gemfile +++ b/Gemfile @@ -35,6 +35,7 @@ gem 'uglifier', '>= 1.3.0' gem 'will_paginate', '~> 3.0' gem 'tubesock' gem 'faye-websocket' +gem 'nokogiri' group :development do gem 'better_errors', platform: :ruby diff --git a/Gemfile.lock b/Gemfile.lock index 268f8596..9dda22e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -361,6 +361,7 @@ DEPENDENCIES jquery-turbolinks kramdown newrelic_rpm + nokogiri nyan-cat-formatter pg pry diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 658a8fb5..9eabb874 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -1,3 +1,4 @@ +require 'nokogiri' require File.expand_path('../../../lib/active_model/validations/boolean_presence_validator', __FILE__) class Exercise < ActiveRecord::Base @@ -105,6 +106,14 @@ class Exercise < ActiveRecord::Base exercise end + def from_proforma_xml(xml_string) + # how to extract the proforma functionality into a different module in rails? + xml = Nokogiri::XML(xml_string) + self.title = xml.xpath('/root/p:task/p:meta-data/p:title/text()')[0].content + self.description = xml.xpath('/root/p:task/p:description/text()')[0].content, + self.execution_environment_id = 1 + end + def generate_token self.token ||= SecureRandom.hex(4) end From 71dda088d1c2d17d18fbf2a0f6915263b6865fff Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Fri, 12 Feb 2016 11:03:17 +0100 Subject: [PATCH 19/29] Associate code harbor links with current user always - this applies to creations and updates - code harbor links are only every edited in the context of the authenticated user (leoselig/codeocean#1) --- app/controllers/code_harbor_links_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/code_harbor_links_controller.rb b/app/controllers/code_harbor_links_controller.rb index 4763976b..a4736f26 100644 --- a/app/controllers/code_harbor_links_controller.rb +++ b/app/controllers/code_harbor_links_controller.rb @@ -35,6 +35,7 @@ class CodeHarborLinksController < ApplicationController # POST /code_harbor_links.json def create @code_harbor_link = CodeHarborLink.new(code_harbor_link_params) + @code_harbor_link.user = current_user authorize! create_and_respond(object: @code_harbor_link) end From 1c3a1a6aaba3f07222f9f1959bfe9a2a4f1141f9 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Fri, 12 Feb 2016 11:08:14 +0100 Subject: [PATCH 20/29] Authenticate action import_proforma_xml via OAuth2 - currently done manually, we should definitely consider a gem here (doorkeeper) - right now, the provided Bearer token from the Authorization header is just looked up in the configured code harbor links of the current user, if one is found -> authenticated -> exercise gets imported (leoselig/codeocean#1) --- app/controllers/exercises_controller.rb | 50 +++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 39324272..85a3650b 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -67,11 +67,55 @@ class ExercisesController < ApplicationController end def import_thin_common_cartridge - logger.info(request.headers['Authorization']) - logger.info(request.headers['Authorisation']) - render :nothing => true, :status => 200, :content_type => 'text/html' + begin + user = user_for_oauth2_request() + exercise = Exercise.new + exercise.from_proforma_xml(request.body.read) + exercise.update(:user => user) + saved = exercise.save + if saved + render :text => 'SUCCESS', :status => 200 + else + render :text => 'Invalid exercise', :status => 400 + end + rescue => error + if error.class == Hash + render :text => error.message, :status => error.status + else + raise error + render :text => '', :status => 500 + end + end end + def user_for_oauth2_request + authorizationHeader = request.headers['Authorization'] + if authorizationHeader == nil + raise ({status: 401, message: 'No Authorization header'}) + end + + oauth2Token = authorizationHeader.split(' ')[1] + if oauth2Token == nil || oauth2Token.size == 0 + raise ({status: 401, message: 'No token in Authorization header'}) + end + + user = user_by_code_harbor_token(oauth2Token) + if user == nil + raise ({status: 401, message: 'Unknown OAuth2 token'}) + end + + return user + end + private :user_for_oauth2_request + + def user_by_code_harbor_token(oauth2Token) + link = CodeHarborLink.where(:oauth2token => oauth2Token)[0] + if link != nil + return link.user + end + end + private :user_by_code_harbor_token + def exercise_params params[:exercise].permit(:description, :execution_environment_id, :file_id, :instructions, :public, :hide_file_tree, :team_id, :title, files_attributes: file_attributes).merge(user_id: current_user.id, user_type: current_user.class.name) end From f787445e5bf2ff8f84199aeccf81f1b519c9535b Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Fri, 12 Feb 2016 11:10:25 +0100 Subject: [PATCH 21/29] Rename #import_thin_common_cartridge to #import_proforma_xml - everywhere (leoselig/codeocean#1) --- app/controllers/exercises_controller.rb | 8 ++++---- config/routes.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 85a3650b..25f522f3 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -11,9 +11,9 @@ class ExercisesController < ApplicationController before_action :set_file_types, only: [:create, :edit, :new, :update] before_action :set_teams, only: [:create, :edit, :new, :update] - skip_before_filter :verify_authenticity_token, only: [:import_thin_common_cartridge] - skip_after_action :verify_authorized, only: [:import_thin_common_cartridge] - skip_after_action :verify_policy_scoped, only: [:import_thin_common_cartridge] + skip_before_filter :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] def authorize! authorize(@exercise || @exercises) @@ -66,7 +66,7 @@ class ExercisesController < ApplicationController def edit end - def import_thin_common_cartridge + def import_proforma_xml begin user = user_for_oauth2_request() exercise = Exercise.new diff --git a/config/routes.rb b/config/routes.rb index 5c8a8c34..72ccb489 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -41,7 +41,7 @@ Rails.application.routes.draw do resources :hints end - post '/thin_common_cartridge' => 'exercises#import_thin_common_cartridge' + post '/import_proforma_xml' => 'exercises#import_proforma_xml' resources :exercises do collection do From 773088798c6f2568202b027a50b23a4212d946e8 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Sat, 13 Feb 2016 11:54:30 +0100 Subject: [PATCH 22/29] Fix array to string cast error - accidental trailing comma caused this (apparently that's a thing in Ruby...) - cleaned up attribute assignments a little bit (persisted/validated/neither assignments) (leoselig/codeocean#1) --- app/controllers/exercises_controller.rb | 5 +++-- app/models/exercise.rb | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 25f522f3..07bd033d 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -70,8 +70,9 @@ class ExercisesController < ApplicationController begin user = user_for_oauth2_request() exercise = Exercise.new - exercise.from_proforma_xml(request.body.read) - exercise.update(:user => user) + request_body = request.body.read + exercise.from_proforma_xml(request_body) + exercise.user = user saved = exercise.save if saved render :text => 'SUCCESS', :status => 200 diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 9eabb874..1b917ecb 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -109,8 +109,11 @@ class Exercise < ActiveRecord::Base def from_proforma_xml(xml_string) # how to extract the proforma functionality into a different module in rails? xml = Nokogiri::XML(xml_string) - self.title = xml.xpath('/root/p:task/p:meta-data/p:title/text()')[0].content - self.description = xml.xpath('/root/p:task/p:description/text()')[0].content, + xml.collect_namespaces + self.attributes = { + title: xml.xpath('/root/p:task/p:meta-data/p:title/text()')[0].content, + description: xml.xpath('/root/p:task/p:description/text()')[0].content + } self.execution_environment_id = 1 end From 7cc612ddaf85946d9cf7c1c9826952abc7d234aa Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 18 Feb 2016 16:03:25 +0100 Subject: [PATCH 23/29] Deserialize exercises files in ProFormA-XML - includes determining main file property via comment and template attributes in XML (closes leoselig/codeocean#3) --- app/controllers/exercises_controller.rb | 1 + app/models/exercise.rb | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 07bd033d..69d1f46f 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -77,6 +77,7 @@ class ExercisesController < ApplicationController if saved render :text => 'SUCCESS', :status => 200 else + logger.info(exercise.errors.full_messages) render :text => 'Invalid exercise', :status => 400 end rescue => error diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 1b917ecb..9b29ca02 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -110,9 +110,27 @@ class Exercise < ActiveRecord::Base # how to extract the proforma functionality into a different module in rails? xml = Nokogiri::XML(xml_string) xml.collect_namespaces + description = xml.xpath('/root/p:task/p:description/text()')[0].content self.attributes = { title: xml.xpath('/root/p:task/p:meta-data/p:title/text()')[0].content, - description: xml.xpath('/root/p:task/p:description/text()')[0].content + description: description, + instructions: description + } + xml.xpath('/root/p:task/p:files/p:file').all? { |file| + file_name_split = file.xpath('@filename').first.value.split('.') + file_class = file.xpath('@class').first.value + comment = file.xpath('@comment').first.value + is_main_file = (file_class == 'template') && (comment == 'main') + files.build({ + name: file_name_split.first, + content: file.xpath('text()').first.content, + read_only: false, + hidden: file_class == 'internal', + role: is_main_file ? 'main_file' : 'regular_file', + file_type: FileType.where( + file_extension: ".#{file_name_split.second}" + ).take + }) } self.execution_environment_id = 1 end From f8c5d2ad9626868db5c0cd96a6771a0df6346338 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 18 Feb 2016 17:26:29 +0100 Subject: [PATCH 24/29] Serialize test files from ProFormA-XML (leoselig/codeocean#4) --- app/models/exercise.rb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 9b29ca02..4ea33bee 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -106,27 +106,40 @@ class Exercise < ActiveRecord::Base exercise end + def determine_file_role_from_proforma_file(task_node, file_node) + file_id = file_node.xpath('@id') + file_class = file_node.xpath('@class').first.value + comment = file_node.xpath('@comment').first.value + is_referenced_by_test = task_node.xpath("p:tests/p:test/p:filerefs/p:fileref[@id=#{file_id}]") + if is_referenced_by_test && (file_class == 'internal') + return 'teacher_defined_test' + elsif (file_class == 'template') && (comment == 'main') + return 'main_file' + elsif (file_class == 'internal') && (comment == 'main') + end + return 'regular_file' + end + def from_proforma_xml(xml_string) # how to extract the proforma functionality into a different module in rails? xml = Nokogiri::XML(xml_string) xml.collect_namespaces - description = xml.xpath('/root/p:task/p:description/text()')[0].content + task_node = xml.xpath('/root/p:task') + description = task_node.xpath('p:description/text()')[0].content self.attributes = { - title: xml.xpath('/root/p:task/p:meta-data/p:title/text()')[0].content, + title: task_node.xpath('p:meta-data/p:title/text()')[0].content, description: description, instructions: description } - xml.xpath('/root/p:task/p:files/p:file').all? { |file| + task_node.xpath('p:files/p:file').all? { |file| file_name_split = file.xpath('@filename').first.value.split('.') file_class = file.xpath('@class').first.value - comment = file.xpath('@comment').first.value - is_main_file = (file_class == 'template') && (comment == 'main') files.build({ name: file_name_split.first, content: file.xpath('text()').first.content, read_only: false, hidden: file_class == 'internal', - role: is_main_file ? 'main_file' : 'regular_file', + role: determine_file_role_from_proforma_file(task_node, file), file_type: FileType.where( file_extension: ".#{file_name_split.second}" ).take From 1c5cf0facbc4d1ba8df5c857f397140efa597afc Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 18 Feb 2016 18:32:03 +0100 Subject: [PATCH 25/29] Deserialize feedback message - this fixes the validation error for test files (leoselig/codeocean#4) --- app/models/exercise.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 4ea33bee..b563b863 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -111,8 +111,11 @@ class Exercise < ActiveRecord::Base file_class = file_node.xpath('@class').first.value comment = file_node.xpath('@comment').first.value is_referenced_by_test = task_node.xpath("p:tests/p:test/p:filerefs/p:fileref[@id=#{file_id}]") + is_referenced_by_model_solution = task_node.xpath("p:model-solutions/p:model-solution/p:filerefs/p:fileref[@id=#{file_id}]") if is_referenced_by_test && (file_class == 'internal') return 'teacher_defined_test' + elsif is_referenced_by_model_solution && (file_class == 'internal') + return 'reference_implementation' elsif (file_class == 'template') && (comment == 'main') return 'main_file' elsif (file_class == 'internal') && (comment == 'main') @@ -134,12 +137,15 @@ class Exercise < ActiveRecord::Base task_node.xpath('p:files/p:file').all? { |file| file_name_split = file.xpath('@filename').first.value.split('.') file_class = file.xpath('@class').first.value + role = determine_file_role_from_proforma_file(task_node, file) + feedback_message_nodes = task_node.xpath("p:tests/p:test/p:test-configuration/c:feedback-message/text()") files.build({ name: file_name_split.first, content: file.xpath('text()').first.content, read_only: false, hidden: file_class == 'internal', - role: determine_file_role_from_proforma_file(task_node, file), + role: role, + feedback_message: (role == 'teacher_defined_test') ? feedback_message_nodes.first.content : nil, file_type: FileType.where( file_extension: ".#{file_name_split.second}" ).take @@ -172,4 +178,5 @@ class Exercise < ActiveRecord::Base end end private :valid_main_file? + end From 94c31e35a461e3f8b450c390336ec74a5b9aae3f Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 1 Mar 2016 11:14:53 +0100 Subject: [PATCH 26/29] Some comments and cleanup of exercise.rb percentage calculation --- Gemfile | 1 + Gemfile.lock | 252 ++++++++++++++++++----------------- app/models/exercise.rb | 6 +- lib/docker_client.rb | 3 +- lib/docker_container_pool.rb | 1 + 5 files changed, 138 insertions(+), 125 deletions(-) diff --git a/Gemfile b/Gemfile index e77ae876..bb0f0034 100644 --- a/Gemfile +++ b/Gemfile @@ -35,6 +35,7 @@ gem 'uglifier', '>= 1.3.0' gem 'will_paginate', '~> 3.0' gem 'tubesock' gem 'faye-websocket' +gem 'websocket-client-simple' group :development do gem 'better_errors', platform: :ruby diff --git a/Gemfile.lock b/Gemfile.lock index 268f8596..e0bcd48f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,41 +2,40 @@ GEM remote: https://rubygems.org/ specs: ZenTest (4.11.0) - actionmailer (4.1.14) - actionpack (= 4.1.14) - actionview (= 4.1.14) + actionmailer (4.1.14.1) + actionpack (= 4.1.14.1) + actionview (= 4.1.14.1) mail (~> 2.5, >= 2.5.4) - actionpack (4.1.14) - actionview (= 4.1.14) - activesupport (= 4.1.14) + actionpack (4.1.14.1) + actionview (= 4.1.14.1) + activesupport (= 4.1.14.1) rack (~> 1.5.2) rack-test (~> 0.6.2) - actionview (4.1.14) - activesupport (= 4.1.14) + actionview (4.1.14.1) + activesupport (= 4.1.14.1) builder (~> 3.1) erubis (~> 2.7.0) - activemodel (4.1.14) - activesupport (= 4.1.14) + activemodel (4.1.14.1) + activesupport (= 4.1.14.1) builder (~> 3.1) - activerecord (4.1.14) - activemodel (= 4.1.14) - activesupport (= 4.1.14) + activerecord (4.1.14.1) + activemodel (= 4.1.14.1) + activesupport (= 4.1.14.1) arel (~> 5.0.0) - activerecord-jdbc-adapter (1.3.15) + activerecord-jdbc-adapter (1.3.19) activerecord (>= 2.2) - activerecord-jdbcpostgresql-adapter (1.3.15) - activerecord-jdbc-adapter (~> 1.3.15) + activerecord-jdbcpostgresql-adapter (1.3.19) + activerecord-jdbc-adapter (~> 1.3.19) jdbc-postgres (>= 9.1) - activesupport (4.1.14) + activesupport (4.1.14.1) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.1) tzinfo (~> 1.1) + addressable (2.4.0) arel (5.0.1.20140414130214) - ast (2.0.0) - astrolabe (1.3.0) - parser (>= 2.2.0.pre.3, < 3.0) + ast (2.2.0) autotest-rails (4.2.1) ZenTest (~> 4.5) bcrypt (3.1.10) @@ -50,7 +49,7 @@ GEM bootstrap-will_paginate (0.0.10) will_paginate builder (3.2.2) - byebug (6.0.2) + byebug (8.2.2) capistrano (3.3.5) capistrano-stats (~> 1.1.0) i18n @@ -59,19 +58,20 @@ GEM capistrano-bundler (1.1.4) capistrano (~> 3.1) sshkit (~> 1.2) - capistrano-rails (1.1.2) + capistrano-rails (1.1.6) capistrano (~> 3.1) capistrano-bundler (~> 1.1) capistrano-rvm (0.1.2) capistrano (~> 3.0) sshkit (~> 1.2) capistrano-stats (1.1.1) - capistrano-upload-config (0.6.0) + capistrano-upload-config (0.7.0) capistrano (>= 3.0) - capistrano3-puma (0.9.0) + capistrano3-puma (1.2.1) capistrano (~> 3.0) puma (>= 2.6) - capybara (2.4.4) + capybara (2.6.2) + addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) @@ -82,9 +82,9 @@ GEM activesupport (>= 3.2.0) json (>= 1.7) mime-types (>= 1.16) - childprocess (0.5.6) + childprocess (0.5.9) ffi (~> 1.0, >= 1.0.11) - codeclimate-test-reporter (0.4.7) + codeclimate-test-reporter (0.4.8) simplecov (>= 0.7.1, < 1.0.0) coderay (1.1.0) coffee-rails (4.0.1) @@ -93,13 +93,12 @@ GEM coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.9.1) - colorize (0.7.7) + coffee-script-source (1.10.0) concurrent-ruby (1.0.0) concurrent-ruby (1.0.0-java) concurrent-ruby-ext (1.0.0) concurrent-ruby (~> 1.0.0) - database_cleaner (1.4.1) + database_cleaner (1.5.1) debug_inspector (0.0.2) diff-lcs (1.2.5) docile (1.1.5) @@ -107,34 +106,35 @@ GEM excon (>= 0.38.0) json erubis (2.7.0) - eventmachine (1.0.8) - eventmachine (1.0.8-java) + event_emitter (0.2.5) + eventmachine (1.0.9.1) + eventmachine (1.0.9.1-java) excon (0.45.4) - execjs (2.5.2) + execjs (2.6.0) factory_girl (4.5.0) activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) + factory_girl_rails (4.6.0) factory_girl (~> 4.5.0) railties (>= 3.0.0) - faraday (0.9.1) + faraday (0.9.2) multipart-post (>= 1.2, < 3) - faye-websocket (0.10.0) + faye-websocket (0.10.2) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) - ffi (1.9.8) - ffi (1.9.8-java) + ffi (1.9.10) + ffi (1.9.10-java) forgery (0.6.0) - highline (1.7.1) + highline (1.7.8) hike (1.2.3) i18n (0.7.0) - ims-lti (1.1.8) + ims-lti (1.1.10) builder oauth (~> 0.4.5) - jbuilder (2.2.13) - activesupport (>= 3.0.0, < 5) + jbuilder (2.4.1) + activesupport (>= 3.0.0, < 5.1) multi_json (~> 1.2) - jdbc-postgres (9.4.1200) - jquery-rails (3.1.2) + jdbc-postgres (9.4.1206) + jquery-rails (3.1.4) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) jquery-turbolinks (2.1.0) @@ -142,115 +142,117 @@ GEM turbolinks json (1.8.3) json (1.8.3-java) - jwt (1.4.1) - kramdown (1.6.0) + jwt (1.5.1) + kramdown (1.9.0) mail (2.6.3) mime-types (>= 1.16, < 3) method_source (0.8.2) mime-types (2.99) - mini_portile (0.6.2) - minitest (5.8.3) + mini_portile2 (2.0.0) + minitest (5.8.4) multi_json (1.11.2) multi_xml (0.5.5) multipart-post (2.0.0) net-scp (1.2.1) net-ssh (>= 2.6.5) - net-ssh (2.9.2) - newrelic_rpm (3.11.2.286) - nokogiri (1.6.6.2) - mini_portile (~> 0.6.0) - nokogiri (1.6.6.2-java) + net-ssh (3.0.2) + newrelic_rpm (3.14.3.313) + nokogiri (1.6.7.2) + mini_portile2 (~> 2.0.0.rc2) + nokogiri (1.6.7.2-java) nyan-cat-formatter (0.11) rspec (>= 2.99, >= 2.14.2, < 4) oauth (0.4.7) - oauth2 (1.0.0) + oauth2 (1.1.0) faraday (>= 0.8, < 0.10) - jwt (~> 1.0) + jwt (~> 1.0, < 1.5.2) multi_json (~> 1.3) multi_xml (~> 0.5) - rack (~> 1.2) - parser (2.2.0.3) - ast (>= 1.1, < 3.0) - pg (0.18.1) - polyamorous (1.2.0) + rack (>= 1.2, < 3) + parser (2.3.0.6) + ast (~> 2.2) + pg (0.18.4) + polyamorous (1.3.0) activerecord (>= 3.0) - powerpack (0.1.0) - pry (0.10.1) + powerpack (0.1.1) + pry (0.10.3) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) - pry (0.10.1-java) + pry (0.10.3-java) coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) spoon (~> 0.0) puma (2.15.3) puma (2.15.3-java) - pundit (0.3.0) + pundit (1.1.0) activesupport (>= 3.0.0) rack (1.5.5) rack-test (0.6.3) rack (>= 1.0) - rails (4.1.14) - actionmailer (= 4.1.14) - actionpack (= 4.1.14) - actionview (= 4.1.14) - activemodel (= 4.1.14) - activerecord (= 4.1.14) - activesupport (= 4.1.14) + rails (4.1.14.1) + actionmailer (= 4.1.14.1) + actionpack (= 4.1.14.1) + actionview (= 4.1.14.1) + activemodel (= 4.1.14.1) + activerecord (= 4.1.14.1) + activesupport (= 4.1.14.1) bundler (>= 1.3.0, < 2.0) - railties (= 4.1.14) + railties (= 4.1.14.1) sprockets-rails (~> 2.0) - rails-i18n (4.0.4) - i18n (~> 0.6) + rails-i18n (4.0.8) + i18n (~> 0.7) railties (~> 4.0) - railties (4.1.14) - actionpack (= 4.1.14) - activesupport (= 4.1.14) + railties (4.1.14.1) + actionpack (= 4.1.14.1) + activesupport (= 4.1.14.1) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.0.0) - rake (10.4.2) - ransack (1.6.6) + rainbow (2.1.0) + rake (10.5.0) + ransack (1.7.0) actionpack (>= 3.0) activerecord (>= 3.0) activesupport (>= 3.0) i18n polyamorous (~> 1.2) - rdoc (4.2.0) - rspec (3.1.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) + rdoc (4.2.2) + json (~> 1.4) + rspec (3.4.0) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) rspec-autotest (1.0.0) rspec-core (>= 2.99.0.beta1, < 4.0.0) - rspec-core (3.1.7) - rspec-support (~> 3.1.0) - rspec-expectations (3.1.2) + rspec-core (3.4.2) + rspec-support (~> 3.4.0) + rspec-expectations (3.4.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.1.0) - rspec-mocks (3.1.3) - rspec-support (~> 3.1.0) - rspec-rails (3.1.0) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-support (~> 3.1.0) - rspec-support (3.1.2) - rubocop (0.30.0) - astrolabe (~> 1.3) - parser (>= 2.2.0.1, < 3.0) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-rails (3.4.2) + actionpack (>= 3.0, < 4.3) + activesupport (>= 3.0, < 4.3) + railties (>= 3.0, < 4.3) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) + rspec-support (~> 3.4.0) + rspec-support (3.4.1) + rubocop (0.37.2) + parser (>= 2.3.0.4, < 3.0) powerpack (~> 0.1) rainbow (>= 1.99.1, < 3.0) - ruby-progressbar (~> 1.4) - rubocop-rspec (1.2.2) + ruby-progressbar (~> 1.7) + unicode-display_width (~> 0.3) + rubocop-rspec (1.4.0) ruby-progressbar (1.7.5) - rubytree (0.9.4) + rubytree (0.9.7) json (~> 1.8) - structured_warnings (~> 0.1) + structured_warnings (~> 0.2) rubyzip (1.1.7) sass (3.2.19) sass-rails (4.0.5) @@ -261,17 +263,17 @@ GEM sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - selenium-webdriver (2.45.0) + selenium-webdriver (2.52.0) childprocess (~> 0.5) multi_json (~> 1.0) rubyzip (~> 1.0) websocket (~> 1.0) - simplecov (0.9.2) + simplecov (0.11.2) docile (~> 1.1.0) - multi_json (~> 1.0) - simplecov-html (~> 0.9.0) - simplecov-html (0.9.0) - slim (3.0.3) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + slim (3.0.6) temple (~> 0.7.3) tilt (>= 1.3.3, < 2.1) slop (3.6.0) @@ -281,7 +283,7 @@ GEM oauth2 (>= 0.8.0) spoon (0.0.4) ffi - spring (1.3.4) + spring (1.6.3) sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) @@ -291,12 +293,11 @@ GEM actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) - sshkit (1.7.1) - colorize (>= 0.7.0) + sshkit (1.8.1) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) structured_warnings (0.2.0) - temple (0.7.5) + temple (0.7.6) thor (0.19.1) thread_safe (0.3.5) thread_safe (0.3.5-java) @@ -308,21 +309,25 @@ GEM coffee-rails tzinfo (1.2.2) thread_safe (~> 0.1) - uglifier (2.7.1) + uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) - web-console (2.1.2) + unicode-display_width (0.3.1) + web-console (2.3.0) activemodel (>= 4.0) binding_of_caller (>= 0.7.2) railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) - websocket (1.2.1) - websocket-driver (0.6.2) + websocket (1.2.2) + websocket-client-simple (0.2.4) + event_emitter + websocket + websocket-driver (0.6.3) websocket-extensions (>= 0.1.0) - websocket-driver (0.6.2-java) + websocket-driver (0.6.3-java) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.2) - will_paginate (3.0.7) + will_paginate (3.1.0) xpath (2.0.0) nokogiri (~> 1.3) @@ -387,4 +392,5 @@ DEPENDENCIES turbolinks uglifier (>= 1.3.0) web-console (~> 2.0) + websocket-client-simple will_paginate (~> 3.0) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 658a8fb5..f86a084c 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -29,7 +29,11 @@ class Exercise < ActiveRecord::Base def average_percentage - (average_score / maximum_score * 100).round if average_score and maximum_score != 0.0 else 0 + if average_score and maximum_score != 0.0 + (average_score / maximum_score * 100).round + else + 0 + end end def average_score diff --git a/lib/docker_client.rb b/lib/docker_client.rb index f1d855ac..3aaba69f 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -96,8 +96,9 @@ class DockerClient #Rails.logger.info "docker_client: self.create_container with creation options:" #Rails.logger.info(container_creation_options(execution_environment)) container = Docker::Container.create(container_creation_options(execution_environment)) + # container.start sometimes creates the passed local_workspace_path on disk (depending on the setup). + # this is however not guaranteed and caused issues on the server already. Therefore create the necessary folders manually! local_workspace_path = generate_local_workspace_path - # container.start always creates the passed local_workspace_path on disk. Seems like we have to live with that, therefore we can also just create the empty folder ourselves. FileUtils.mkdir(local_workspace_path) container.start(container_start_options(execution_environment, local_workspace_path)) container.start_time = Time.now diff --git a/lib/docker_container_pool.rb b/lib/docker_container_pool.rb index 1921afdb..7f1f16fd 100644 --- a/lib/docker_container_pool.rb +++ b/lib/docker_container_pool.rb @@ -48,6 +48,7 @@ class DockerContainerPool end def self.create_container(execution_environment) + Rails.logger.info('trying to create container for execution environment: ' + execution_environment.to_s) container = DockerClient.create_container(execution_environment) container.status = 'available' #Rails.logger.debug('created container ' + container.to_s + ' for execution environment ' + execution_environment.to_s) From b269a738f57bf6a493ad1f0656b2efccddbde832 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 1 Mar 2016 11:25:49 +0100 Subject: [PATCH 27/29] renamed execute_websocket_command to open_websocket_connection, because we now run the command after all listeners in the submissions controller were attached --- app/controllers/submissions_controller.rb | 5 +++++ lib/docker_client.rb | 10 ++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 5bac07c4..1bc5cecf 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -139,6 +139,11 @@ class SubmissionsController < ApplicationController Rails.logger.debug('Rescued parsing error, sent the received client data to docker:' + data) end end + + # Send command after all listeners are attached. + # Newline required to flush + socket.send command + "\n" + Rails.logger.info('Sent command: ' + command.to_s) else kill_socket(tubesock) end diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 3aaba69f..80986377 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -218,7 +218,7 @@ class DockerClient end #called when the user clicks the "Run" button - def execute_websocket_command(command, before_execution_block, output_consuming_block) + def open_websocket_connection(command, before_execution_block, output_consuming_block) @container = DockerContainerPool.get_container(@execution_environment) if @container @container.status = :executing @@ -231,10 +231,7 @@ class DockerClient end # TODO: catch exception if socket could not be created @socket ||= create_socket(@container) - # Newline required to flush - @socket.send command + "\n" - Rails.logger.info('Sent command: ' + command.to_s) - {status: :container_running, socket: @socket, container: @container} + {status: :container_running, socket: @socket, container: @container, command: command} else {status: :container_depleted} end @@ -297,7 +294,8 @@ class DockerClient """ command = submission.execution_environment.run_command % command_substitutions(filename) create_workspace_files = proc { create_workspace_files(container, submission) } - execute_websocket_command(command, create_workspace_files, block) + open_websocket_connection(command, create_workspace_files, block) + # actual run command is run in the submissions controller, after all listeners are attached. end def execute_test_command(submission, filename, &block) From b31a5b37f436d993352f03e4b09e8fdd306512d9 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 1 Mar 2016 11:25:49 +0100 Subject: [PATCH 28/29] renamed execute_websocket_command to open_websocket_connection, because we now run the command after all listeners in the submissions controller were attached --- app/controllers/submissions_controller.rb | 6 ++++++ lib/docker_client.rb | 10 ++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 5bac07c4..8f26d986 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -111,6 +111,7 @@ class SubmissionsController < ApplicationController if result[:status] == :container_running socket = result[:socket] + command = result[:command] socket.on :message do |event| Rails.logger.info( Time.now.getutc.to_s + ": Docker sending: " + event.data) @@ -139,6 +140,11 @@ class SubmissionsController < ApplicationController Rails.logger.debug('Rescued parsing error, sent the received client data to docker:' + data) end end + + # Send command after all listeners are attached. + # Newline required to flush + socket.send command + "\n" + Rails.logger.info('Sent command: ' + command.to_s) else kill_socket(tubesock) end diff --git a/lib/docker_client.rb b/lib/docker_client.rb index 3aaba69f..80986377 100644 --- a/lib/docker_client.rb +++ b/lib/docker_client.rb @@ -218,7 +218,7 @@ class DockerClient end #called when the user clicks the "Run" button - def execute_websocket_command(command, before_execution_block, output_consuming_block) + def open_websocket_connection(command, before_execution_block, output_consuming_block) @container = DockerContainerPool.get_container(@execution_environment) if @container @container.status = :executing @@ -231,10 +231,7 @@ class DockerClient end # TODO: catch exception if socket could not be created @socket ||= create_socket(@container) - # Newline required to flush - @socket.send command + "\n" - Rails.logger.info('Sent command: ' + command.to_s) - {status: :container_running, socket: @socket, container: @container} + {status: :container_running, socket: @socket, container: @container, command: command} else {status: :container_depleted} end @@ -297,7 +294,8 @@ class DockerClient """ command = submission.execution_environment.run_command % command_substitutions(filename) create_workspace_files = proc { create_workspace_files(container, submission) } - execute_websocket_command(command, create_workspace_files, block) + open_websocket_connection(command, create_workspace_files, block) + # actual run command is run in the submissions controller, after all listeners are attached. end def execute_test_command(submission, filename, &block) From ed63a9dfd83623a19d0da2fbd78b107ede83e73e Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Tue, 1 Mar 2016 11:39:41 +0100 Subject: [PATCH 29/29] accidentially added websocket_gem on master branch. This commit removes it again. --- Gemfile | 1 - Gemfile.lock | 5 ----- 2 files changed, 6 deletions(-) diff --git a/Gemfile b/Gemfile index bb0f0034..e77ae876 100644 --- a/Gemfile +++ b/Gemfile @@ -35,7 +35,6 @@ gem 'uglifier', '>= 1.3.0' gem 'will_paginate', '~> 3.0' gem 'tubesock' gem 'faye-websocket' -gem 'websocket-client-simple' group :development do gem 'better_errors', platform: :ruby diff --git a/Gemfile.lock b/Gemfile.lock index e0bcd48f..10284f6f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -106,7 +106,6 @@ GEM excon (>= 0.38.0) json erubis (2.7.0) - event_emitter (0.2.5) eventmachine (1.0.9.1) eventmachine (1.0.9.1-java) excon (0.45.4) @@ -319,9 +318,6 @@ GEM railties (>= 4.0) sprockets-rails (>= 2.0, < 4.0) websocket (1.2.2) - websocket-client-simple (0.2.4) - event_emitter - websocket websocket-driver (0.6.3) websocket-extensions (>= 0.1.0) websocket-driver (0.6.3-java) @@ -392,5 +388,4 @@ DEPENDENCIES turbolinks uglifier (>= 1.3.0) web-console (~> 2.0) - websocket-client-simple will_paginate (~> 3.0)