From aa8870b8c85e2edcf67148cecb551e40611cb9e7 Mon Sep 17 00:00:00 2001 From: "leo.selig" Date: Thu, 4 Feb 2016 09:28:50 +0100 Subject: [PATCH 01/21] 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 02/21] 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 03/21] 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 04/21] 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 05/21] 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 06/21] 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 07/21] 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 08/21] 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 09/21] 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 10/21] =?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 11/21] 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 12/21] 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 13/21] 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 14/21] 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 15/21] 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 16/21] 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 17/21] 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 18/21] 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 19/21] 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 20/21] 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 21/21] 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