From 4ab78c170e24de5db1871745f24399dccaa4e402 Mon Sep 17 00:00:00 2001 From: Karol Date: Wed, 16 Oct 2019 19:19:28 +0200 Subject: [PATCH] add uuid check --- Gemfile | 1 + Gemfile.lock | 1 + app/assets/javascripts/exercises.js.erb | 44 +++++++++++++++++++ app/assets/stylesheets/exercises.css.scss | 27 ++++++++++++ app/controllers/exercises_controller.rb | 44 ++++++++++++++++++- app/policies/exercise_policy.rb | 2 +- app/views/exercises/_export_actions.html.slim | 20 +++++++++ .../exercises/_export_dialogcontent.html.slim | 5 +++ app/views/exercises/index.html.slim | 4 +- config/locales/en.yml | 1 + config/routes.rb | 3 +- ...nt_id_client_secret_to_codeharbor_links.rb | 7 --- ..._rename_oauth2token_in_codeharbor_links.rb | 6 +++ db/schema.rb | 4 +- 14 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 app/views/exercises/_export_actions.html.slim create mode 100644 app/views/exercises/_export_dialogcontent.html.slim delete mode 100644 db/migrate/20190818104954_add_push_url_client_id_client_secret_to_codeharbor_links.rb create mode 100644 db/migrate/20190818104954_add_push_url_rename_oauth2token_in_codeharbor_links.rb diff --git a/Gemfile b/Gemfile index 90052eff..056ce5d7 100644 --- a/Gemfile +++ b/Gemfile @@ -36,6 +36,7 @@ gem 'webpacker' gem 'rest-client' gem 'rubyzip' gem 'mnemosyne-ruby' +gem 'faraday' gem 'proforma', git: 'git://github.com/openHPI/proforma.git' # use version not master gem 'whenever', require: false gem 'rails-timeago' diff --git a/Gemfile.lock b/Gemfile.lock index 6388bfde..4f353f77 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -426,6 +426,7 @@ DEPENDENCIES docker-api eventmachine (= 1.0.9.1) factory_bot_rails + faraday faye-websocket forgery headless diff --git a/app/assets/javascripts/exercises.js.erb b/app/assets/javascripts/exercises.js.erb index 8eb64f4f..26feb6aa 100644 --- a/app/assets/javascripts/exercises.js.erb +++ b/app/assets/javascripts/exercises.js.erb @@ -238,6 +238,48 @@ $(document).on('turbolinks:load', function() { }; + var observeExportStartButtons = function(){ + $('.export-start').on('click', function(e){ + e.preventDefault(); + $('#export-modal').modal({ + height: 250 + }); + $('#export-modal').modal('show'); + exportExerciseStart($(this).attr('data-exercise-id')); + }); + } + + var exportExerciseStart = function(exerciseID) { + var $exerciseDiv = $('#export-exercise'); + // var accountLinkID = $exerciseDiv.attr('data-account-link'); + var $messageDiv = $exerciseDiv.children('.export-message'); + var $actionsDiv = $exerciseDiv.children('.export-exercise-actions'); + + $messageDiv.html('requesting status'); + $actionsDiv.html('spinning'); + + return $.ajax({ + type: 'POST', + url: '/exercises/' + exerciseID + '/export_external_check', + // data: { + // account_link: accountLinkID + // }, + dataType: 'json', + success: function(response) { + if (response.error) { + $messageDiv.html(response.error); + $actionsDiv.html('Retry?'); + } + $messageDiv.html(response.message); + return $actionsDiv.html(response.actions); + }, + error: function(a, b, c) { + return alert('error:' + c); + } + }); + }; + + var overrideTextareaTabBehavior = function() { $('.form-group textarea[name$="[content]"]').on('keydown', function(event) { if (event.which === TAB_KEY_CODE) { @@ -293,6 +335,7 @@ $(document).on('turbolinks:load', function() { // ignore tags table since it is in the dom before other tables if ($('table:not(#tags-table)').isPresent()) { enableBatchUpdate(); + observeExportStartButtons(); } else if ($('.edit_exercise, .new_exercise').isPresent()) { execution_environments = $('form').data('execution-environments'); file_types = $('form').data('file-types'); @@ -303,6 +346,7 @@ $(document).on('turbolinks:load', function() { observeExecutionEnvironment(); observeUnpublishedState(); overrideTextareaTabBehavior(); + } else if ($('#files.jstree').isPresent()) { var fileTypeSelect = $('#code_ocean_file_file_type_id'); fileTypeSelect.on("change", function() {updateFileTemplates(fileTypeSelect.val())}); diff --git a/app/assets/stylesheets/exercises.css.scss b/app/assets/stylesheets/exercises.css.scss index ce3195c1..bc611d17 100644 --- a/app/assets/stylesheets/exercises.css.scss +++ b/app/assets/stylesheets/exercises.css.scss @@ -176,3 +176,30 @@ a.file-heading { } } } + +#export-modal { + .modal-content { + min-height: unset; + height: 300px; + } +} + +#export-exercise{ + display: flex; +} + +.export-message { + flex-grow: 1; + font-size: 12px; + padding-right: 5px; +} + +.export-exercise-actions { + max-width: 110px; + min-width: 110px; +} + +.export-button { + font-size: 12px; + width: 100%; +} diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index f007f443..580c8511 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -7,7 +7,7 @@ class ExercisesController < ApplicationController before_action :handle_file_uploads, only: [:create, :update] before_action :set_execution_environments, only: [:create, :edit, :new, :update] - before_action :set_exercise_and_authorize, only: MEMBER_ACTIONS + [:push_proforma_xml, :clone, :implement, :working_times, :intervention, :search, :run, :statistics, :submit, :reload, :feedback, :study_group_dashboard] + before_action :set_exercise_and_authorize, only: MEMBER_ACTIONS + [:push_proforma_xml, :clone, :implement, :working_times, :intervention, :search, :run, :statistics, :submit, :reload, :feedback, :study_group_dashboard, :export_external_check] before_action :set_external_user_and_authorize, only: [:statistics] before_action :set_file_types, only: [:create, :edit, :new, :update] before_action :set_course_token, only: [:implement] @@ -119,6 +119,48 @@ class ExercisesController < ApplicationController end end + def export_external_check + @codeharbor_link = current_user.codeharbor_link + url = 'http://localhost:3001/import_uuid_check' + + conn = Faraday.new(url: url) do |faraday| + faraday.options[:open_timeout] = 5 + faraday.options[:timeout] = 5 + + faraday.adapter Faraday.default_adapter + end + + error = false + response_hash = {} + message = '' + begin + response = conn.post do |req| + req.headers['Content-Type'] = 'application/json' + req.headers['Authorization'] = 'Bearer ' + @codeharbor_link.api_key + req.body = {uuid: @exercise.uuid}.to_json + end + response_hash = JSON.parse(response.body, symbolize_names: true) + message = response_hash[:message] + rescue Faraday::ClientError + message = 'an error occured' + error = true + end + + render json: { + message: message, + actions: render_to_string( + partial: 'export_actions', + locals: { + exercise: @exercise, + exercise_found: response_hash[:exercise_found], + update_right: response_hash[:update_right], + error: error + } + ) + + }, status: 200 + end + def import_uuid_check user = user_for_oauth2_request return render json: {}, status: 401 if user.nil? diff --git a/app/policies/exercise_policy.rb b/app/policies/exercise_policy.rb index 8a5679ee..e0a8d2a5 100644 --- a/app/policies/exercise_policy.rb +++ b/app/policies/exercise_policy.rb @@ -7,7 +7,7 @@ class ExercisePolicy < AdminOrAuthorPolicy define_method(action) { admin? || teacher? } end - [:clone?, :destroy?, :edit?, :statistics?, :update?, :feedback?, :push_proforma_xml?].each do |action| + [:clone?, :destroy?, :edit?, :statistics?, :update?, :feedback?, :push_proforma_xml?, :export_external_check?].each do |action| define_method(action) { admin? || author? } end diff --git a/app/views/exercises/_export_actions.html.slim b/app/views/exercises/_export_actions.html.slim new file mode 100644 index 00000000..4274ddc4 --- /dev/null +++ b/app/views/exercises/_export_actions.html.slim @@ -0,0 +1,20 @@ +- if error + = button_tag type: 'button', class:'btn btn-primary pull-right export-button', onclick: "exportExerciseStart(#{exercise.id})" do + i.fa.fa-refresh.confirm-icon + = ' Retry' +- else + - if exercise_found + - if update_right + = button_tag type: 'button', class:'btn btn-primary pull-right export-action export-button', data: {'export-type' => 'export'} do + i.fa.fa-check.confirm-icon + = ' Overwrite' + = button_tag type: 'button', class:'btn btn-primary pull-right export-action export-button', data: {'export-type' => 'create_new'} do + i.fa.fa-check.confirm-icon-alt + = ' Create new' + - else + = button_tag type: 'button', class:'btn btn-primary pull-right export-action export-button', data: {'export-type' => 'export'} do + i.fa.fa-check.confirm-icon + = ' Export' += button_tag type: 'submit', class:'btn btn-secondary pull-right export-button', data: {dismiss: 'modal'} do + i.fa.fa-remove.abort-icon + = ' Abort' diff --git a/app/views/exercises/_export_dialogcontent.html.slim b/app/views/exercises/_export_dialogcontent.html.slim new file mode 100644 index 00000000..92066666 --- /dev/null +++ b/app/views/exercises/_export_dialogcontent.html.slim @@ -0,0 +1,5 @@ +#export-exercise + .export-message + = 'This should not be seen' + .export-exercise-actions + = 'This neither' diff --git a/app/views/exercises/index.html.slim b/app/views/exercises/index.html.slim index 2b854d22..22004850 100644 --- a/app/views/exercises/index.html.slim +++ b/app/views/exercises/index.html.slim @@ -46,7 +46,9 @@ h1 = Exercise.model_name.human(count: 2) li = link_to(t('activerecord.models.user_exercise_feedback.other'), feedback_exercise_path(exercise), class: 'dropdown-item') if policy(exercise).feedback? li = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete, class: 'dropdown-item') if policy(exercise).destroy? li = link_to(t('.clone'), clone_exercise_path(exercise), data: {confirm: t('shared.confirm_destroy')}, method: :post, class: 'dropdown-item') if policy(exercise).clone? - li = link_to(t('exercises.export_codeharbor.label'), push_proforma_xml_exercise_path(exercise), method: :post, class: 'dropdown-item') if policy(exercise).push_proforma_xml? + li = link_to(t('exercises.export_codeharbor.label'), '', class: 'dropdown-item export-start', data: {'exercise-id' => exercise.id}) if policy(exercise).push_proforma_xml? = render('shared/pagination', collection: @exercises) p = render('shared/new_button', model: Exercise) + += render('shared/modal', id: 'export-modal', title: t('exercises.export_codeharbor.dialogtitle'), template: 'exercises/_export_dialogcontent') diff --git a/config/locales/en.yml b/config/locales/en.yml index f67c6c43..8cb2d110 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -326,6 +326,7 @@ en: fail: Failed to push the exercise to CodeHarbor. label: Export to Codeharbor success: Successfully pushed the exercise to CodeHarbor. + dialogtitle: Export to Codeharbor file_form: hints: feedback_message: This message is used as a hint for failing tests. diff --git a/config/routes.rb b/config/routes.rb index 52d33d3c..388fc175 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -82,10 +82,11 @@ Rails.application.routes.draw do post :search get :statistics get :feedback - post :push_proforma_xml get :reload post :submit get 'study_group_dashboard/:study_group_id', to: 'exercises#study_group_dashboard' + post :push_proforma_xml + post :export_external_check end end diff --git a/db/migrate/20190818104954_add_push_url_client_id_client_secret_to_codeharbor_links.rb b/db/migrate/20190818104954_add_push_url_client_id_client_secret_to_codeharbor_links.rb deleted file mode 100644 index 9d041be6..00000000 --- a/db/migrate/20190818104954_add_push_url_client_id_client_secret_to_codeharbor_links.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddPushUrlClientIdClientSecretToCodeharborLinks < ActiveRecord::Migration[5.2] - def change - add_column :codeharbor_links, :push_url, :string - add_column :codeharbor_links, :client_id, :string - add_column :codeharbor_links, :client_secret, :string - end -end diff --git a/db/migrate/20190818104954_add_push_url_rename_oauth2token_in_codeharbor_links.rb b/db/migrate/20190818104954_add_push_url_rename_oauth2token_in_codeharbor_links.rb new file mode 100644 index 00000000..d3a3c01f --- /dev/null +++ b/db/migrate/20190818104954_add_push_url_rename_oauth2token_in_codeharbor_links.rb @@ -0,0 +1,6 @@ +class AddPushUrlRenameOauth2tokenInCodeharborLinks < ActiveRecord::Migration[5.2] + def change + add_column :codeharbor_links, :push_url, :string + rename_column :codeharbor_links, :oauth2token, :api_key + end +end diff --git a/db/schema.rb b/db/schema.rb index 34d1802a..6cd22c8f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -29,13 +29,11 @@ ActiveRecord::Schema.define(version: 2019_10_08_163045) do end create_table "codeharbor_links", force: :cascade do |t| - t.string "oauth2token", limit: 255 + t.string "api_key", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "user_id" t.string "push_url" - t.string "client_id" - t.string "client_secret" t.index ["user_id"], name: "index_codeharbor_links_on_user_id" end