add check_uuid_url to codeharbor_link
This commit is contained in:
@ -28,17 +28,8 @@ $(document).on('turbolinks:load', function() {
|
|||||||
return replace(Array(32).join('x'));
|
return replace(Array(32).join('x'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.generate-api_key').on('click', function () {
|
||||||
$('.generate-client-id').on('click', function () {
|
$('.api_key').val(generateRandomHex32())
|
||||||
$('.client-id').val(generateUUID());
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.generate-client-secret').on('click', function () {
|
|
||||||
$('.client-secret').val(generateRandomHex32());
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.generate-oauth2-token').on('click', function () {
|
|
||||||
$('.oauth2-token').val(generateRandomHex32())
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,18 +261,16 @@ $(document).on('turbolinks:load', function() {
|
|||||||
var $messageDiv = $exerciseDiv.children('.export-message');
|
var $messageDiv = $exerciseDiv.children('.export-message');
|
||||||
var $actionsDiv = $exerciseDiv.children('.export-exercise-actions');
|
var $actionsDiv = $exerciseDiv.children('.export-exercise-actions');
|
||||||
|
|
||||||
$messageDiv.html('requesting status');
|
$messageDiv.removeClass('export-failure');
|
||||||
$actionsDiv.html('spinning');
|
|
||||||
|
$messageDiv.html('<%= I18n.t('exercises.export_codeharbor.checking_codeharbor') %>');
|
||||||
|
$actionsDiv.html('<div class="spinner-border"></div>');
|
||||||
|
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: '/exercises/' + exerciseID + '/export_external_check',
|
url: '/exercises/' + exerciseID + '/export_external_check',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
if (response.error) {
|
|
||||||
$messageDiv.html(response.error);
|
|
||||||
$actionsDiv.html('Retry?');
|
|
||||||
}
|
|
||||||
$messageDiv.html(response.message);
|
$messageDiv.html(response.message);
|
||||||
return $actionsDiv.html(response.actions);
|
return $actionsDiv.html(response.actions);
|
||||||
},
|
},
|
||||||
@ -380,7 +378,6 @@ $(document).on('turbolinks:load', function() {
|
|||||||
observeExecutionEnvironment();
|
observeExecutionEnvironment();
|
||||||
observeUnpublishedState();
|
observeUnpublishedState();
|
||||||
overrideTextareaTabBehavior();
|
overrideTextareaTabBehavior();
|
||||||
|
|
||||||
} else if ($('#files.jstree').isPresent()) {
|
} else if ($('#files.jstree').isPresent()) {
|
||||||
var fileTypeSelect = $('#code_ocean_file_file_type_id');
|
var fileTypeSelect = $('#code_ocean_file_file_type_id');
|
||||||
fileTypeSelect.on("change", function() {updateFileTemplates(fileTypeSelect.val())});
|
fileTypeSelect.on("change", function() {updateFileTemplates(fileTypeSelect.val())});
|
||||||
|
@ -179,8 +179,11 @@ a.file-heading {
|
|||||||
|
|
||||||
#export-modal {
|
#export-modal {
|
||||||
.modal-content {
|
.modal-content {
|
||||||
min-height: unset;
|
min-height: 300px;
|
||||||
height: 300px;
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ class CodeharborLinksController < ApplicationController
|
|||||||
before_action :set_codeharbor_link, only: %i[show edit update destroy]
|
before_action :set_codeharbor_link, only: %i[show edit update destroy]
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@codeharbor_link = CodeharborLink.new
|
base_url = CodeOcean::Config.new(:code_ocean).read[:codeharbor][:url]
|
||||||
|
@codeharbor_link = CodeharborLink.new(push_url: base_url + '/import_exercise', check_uuid_url: base_url + '/import_uuid_check')
|
||||||
authorize!
|
authorize!
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -42,6 +43,6 @@ class CodeharborLinksController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def codeharbor_link_params
|
def codeharbor_link_params
|
||||||
params.require(:codeharbor_link).permit(:push_url, :oauth2token, :client_id, :client_secret)
|
params.require(:codeharbor_link).permit(:push_url, :check_uuid_url, :api_key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ class ExercisesController < ApplicationController
|
|||||||
|
|
||||||
before_action :handle_file_uploads, only: [:create, :update]
|
before_action :handle_file_uploads, only: [:create, :update]
|
||||||
before_action :set_execution_environments, only: [:create, :edit, :new, :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, :export_external_check, :export_external_confirm]
|
before_action :set_exercise_and_authorize, only: MEMBER_ACTIONS + [:clone, :implement, :working_times, :intervention, :search, :run, :statistics, :submit, :reload, :feedback, :study_group_dashboard, :export_external_check, :export_external_confirm]
|
||||||
before_action :set_external_user_and_authorize, only: [:statistics]
|
before_action :set_external_user_and_authorize, only: [:statistics]
|
||||||
before_action :set_file_types, only: [:create, :edit, :new, :update]
|
before_action :set_file_types, only: [:create, :edit, :new, :update]
|
||||||
before_action :set_course_token, only: [:implement]
|
before_action :set_course_token, only: [:implement]
|
||||||
@ -107,54 +107,37 @@ class ExercisesController < ApplicationController
|
|||||||
@feedbacks = @exercise.user_exercise_feedbacks.paginate(page: params[:page])
|
@feedbacks = @exercise.user_exercise_feedbacks.paginate(page: params[:page])
|
||||||
end
|
end
|
||||||
|
|
||||||
def push_proforma_xml
|
|
||||||
error = ExerciseService::PushExternal.call(
|
|
||||||
zip: ProformaService::ExportTask.call(exercise: @exercise),
|
|
||||||
codeharbor_link: current_user.codeharbor_link
|
|
||||||
)
|
|
||||||
if error.nil?
|
|
||||||
redirect_to exercises_path, notice: t('exercises.export_codeharbor.success')
|
|
||||||
else
|
|
||||||
redirect_to exercises_path, alert: t('exercises.export_codeharbor.fail')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def export_external_check
|
def export_external_check
|
||||||
@codeharbor_link = current_user.codeharbor_link
|
@codeharbor_link = current_user.codeharbor_link
|
||||||
url = 'http://localhost:3001/import_uuid_check'
|
conn = Faraday.new(url: @codeharbor_link.check_uuid_url) do |faraday|
|
||||||
|
|
||||||
conn = Faraday.new(url: url) do |faraday|
|
|
||||||
faraday.options[:open_timeout] = 5
|
faraday.options[:open_timeout] = 5
|
||||||
faraday.options[:timeout] = 5
|
faraday.options[:timeout] = 5
|
||||||
|
|
||||||
faraday.adapter Faraday.default_adapter
|
faraday.adapter Faraday.default_adapter
|
||||||
end
|
end
|
||||||
|
|
||||||
error = false
|
codeharbor_check = begin
|
||||||
response_hash = {}
|
response = conn.post do |req|
|
||||||
message = ''
|
req.headers['Content-Type'] = 'application/json'
|
||||||
begin
|
req.headers['Authorization'] = 'Bearer ' + @codeharbor_link.api_key
|
||||||
response = conn.post do |req|
|
req.body = {uuid: @exercise.uuid}.to_json
|
||||||
req.headers['Content-Type'] = 'application/json'
|
end
|
||||||
req.headers['Authorization'] = 'Bearer ' + @codeharbor_link.api_key
|
response_hash = JSON.parse(response.body, symbolize_names: true)
|
||||||
req.body = {uuid: @exercise.uuid}.to_json
|
|
||||||
end
|
{error: false}.merge(response_hash.slice(:message, :exercise_found, :update_right))
|
||||||
response_hash = JSON.parse(response.body, symbolize_names: true)
|
rescue Faraday::Error => e
|
||||||
message = response_hash[:message]
|
{error: true, message: t('exercises.export_codeharbor.error', message: e.message)}
|
||||||
rescue Faraday::Error => e
|
end
|
||||||
message = t('exercises.export_codeharbor.error', message: e.message)
|
|
||||||
error = true
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: {
|
render json: {
|
||||||
message: message,
|
message: codeharbor_check[:message],
|
||||||
actions: render_to_string(
|
actions: render_to_string(
|
||||||
partial: 'export_actions',
|
partial: 'export_actions',
|
||||||
locals: {
|
locals: {
|
||||||
exercise: @exercise,
|
exercise: @exercise,
|
||||||
exercise_found: response_hash[:exercise_found],
|
exercise_found: codeharbor_check[:exercise_found],
|
||||||
update_right: response_hash[:update_right],
|
update_right: codeharbor_check[:update_right],
|
||||||
error: error,
|
error: codeharbor_check[:error],
|
||||||
exported: false
|
exported: false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -179,15 +162,12 @@ class ExercisesController < ApplicationController
|
|||||||
message: t('exercises.export_codeharbor.successfully_exported', id: @exercise.id, title: @exercise.title),
|
message: t('exercises.export_codeharbor.successfully_exported', id: @exercise.id, title: @exercise.title),
|
||||||
actions: render_to_string(partial: 'export_actions', locals: {exercise: @exercise, exported: true, error: error})
|
actions: render_to_string(partial: 'export_actions', locals: {exercise: @exercise, exported: true, error: error})
|
||||||
}
|
}
|
||||||
# @exercise, notice: t('controllers.exercise.push_external_notice', account_link: account_link.readable)
|
|
||||||
else
|
else
|
||||||
# logger.debug(error)
|
|
||||||
render json: {
|
render json: {
|
||||||
status: 'fail',
|
status: 'fail',
|
||||||
message: t('exercises.export_codeharbor.export_failed', id: @exercise.id, title: @exercise.title, error: error),
|
message: t('exercises.export_codeharbor.export_failed', id: @exercise.id, title: @exercise.title, error: error),
|
||||||
actions: render_to_string(partial: 'export_actions', locals: {exercise: @exercise, exported: true, error: error})
|
actions: render_to_string(partial: 'export_actions', locals: {exercise: @exercise, exported: true, error: error})
|
||||||
}
|
}
|
||||||
# redirect_to @exercise, alert: t('controllers.account_links.not_working', account_link: account_link.readable)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CodeharborLink < ApplicationRecord
|
class CodeharborLink < ApplicationRecord
|
||||||
validates :oauth2token, presence: true
|
validates :push_url, presence: true
|
||||||
|
validates :check_uuid_url, presence: true
|
||||||
|
validates :api_key, presence: true
|
||||||
|
|
||||||
belongs_to :user, foreign_key: :user_id, class_name: 'InternalUser'
|
belongs_to :user, foreign_key: :user_id, class_name: 'InternalUser'
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
oauth2token
|
id.to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,7 +7,7 @@ class ExercisePolicy < AdminOrAuthorPolicy
|
|||||||
define_method(action) { admin? || teacher? }
|
define_method(action) { admin? || teacher? }
|
||||||
end
|
end
|
||||||
|
|
||||||
[:clone?, :destroy?, :edit?, :statistics?, :update?, :feedback?, :push_proforma_xml?, :export_external_check?, :export_external_confirm?].each do |action|
|
[:clone?, :destroy?, :edit?, :statistics?, :update?, :feedback?, :export_external_check?, :export_external_confirm?].each do |action|
|
||||||
define_method(action) { admin? || author? }
|
define_method(action) { admin? || author? }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
module ExerciseService
|
module ExerciseService
|
||||||
class PushExternal < ServiceBase
|
class PushExternal < ServiceBase
|
||||||
CODEHARBOR_PUSH_LINK = Rails.env.production? ? 'https://codeharbor.openhpi.de/import_exercise' : 'http://localhost:3001/import_exercise'
|
|
||||||
def initialize(zip:, codeharbor_link:)
|
def initialize(zip:, codeharbor_link:)
|
||||||
@zip = zip
|
@zip = zip
|
||||||
@codeharbor_link = codeharbor_link
|
@codeharbor_link = codeharbor_link
|
||||||
@ -11,7 +10,7 @@ module ExerciseService
|
|||||||
def execute
|
def execute
|
||||||
body = @zip.string
|
body = @zip.string
|
||||||
begin
|
begin
|
||||||
conn = Faraday.new(url: CODEHARBOR_PUSH_LINK) do |faraday|
|
conn = Faraday.new(url: @codeharbor_link.push_url) do |faraday|
|
||||||
faraday.adapter Faraday.default_adapter
|
faraday.adapter Faraday.default_adapter
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -4,23 +4,14 @@
|
|||||||
= f.label(:push_url)
|
= f.label(:push_url)
|
||||||
= f.text_field :push_url, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.push_url'), class: 'form-control'
|
= f.text_field :push_url, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.push_url'), class: 'form-control'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label(:oauth2token)
|
= f.label(:check_uuid_url)
|
||||||
|
= f.text_field :check_uuid_url, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.check_uuid_url'), class: 'form-control'
|
||||||
|
.form-group
|
||||||
|
= f.label(:api_key)
|
||||||
.input-group
|
.input-group
|
||||||
= f.text_field(:oauth2token, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.token'), class: 'form-control oauth2-token')
|
= f.text_field(:api_key, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.token'), class: 'form-control api_key')
|
||||||
.input-group-btn
|
.input-group-btn
|
||||||
= button_tag t('codeharbor_link.generate'), type: 'button', class: 'generate-oauth2-token btn btn-default'
|
= button_tag t('codeharbor_link.generate'), type: 'button', class: 'generate-api_key btn btn-default'
|
||||||
.field-element.form-group
|
|
||||||
= f.label(:client_id)
|
|
||||||
.input-group
|
|
||||||
= f.text_field(:client_id, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.client_id'), class: 'form-control client-id')
|
|
||||||
.input-group-btn
|
|
||||||
= button_tag t('codeharbor_link.generate'), type: 'button', class: 'generate-client-id btn btn-default'
|
|
||||||
.field-element.form-group
|
|
||||||
= f.label(:client_secret)
|
|
||||||
.input-group
|
|
||||||
= f.text_field(:client_secret, data: {toggle: 'tooltip', placement: 'bottom'}, title: t('codeharbor_link.info.client_secret'), class: 'form-control client-secret')
|
|
||||||
.input-group-btn
|
|
||||||
= button_tag t('codeharbor_link.generate'), type: 'button', class: 'generate-client-secret btn btn-default'
|
|
||||||
.actions
|
.actions
|
||||||
= render('shared/submit_button', f: f, object: @codeharbor_link)
|
= render('shared/submit_button', f: f, object: @codeharbor_link)
|
||||||
- if @codeharbor_link.persisted?
|
- if @codeharbor_link.persisted?
|
||||||
|
@ -46,7 +46,7 @@ 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('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('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('.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'), '', class: 'dropdown-item export-start', data: {'exercise-id' => exercise.id}) 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).export_external_confirm?
|
||||||
|
|
||||||
= render('shared/pagination', collection: @exercises)
|
= render('shared/pagination', collection: @exercises)
|
||||||
p = render('shared/new_button', model: Exercise)
|
p = render('shared/new_button', model: Exercise)
|
||||||
|
@ -246,7 +246,9 @@ en:
|
|||||||
generate: Generate
|
generate: Generate
|
||||||
info:
|
info:
|
||||||
push_url: |
|
push_url: |
|
||||||
The address on CodeHarbor side your exercise can be exported to. If you don't know what to write here, ask an admin.
|
The url from Codeharbor where your exercise can be exported to. If you don't know what to write here, ask an admin.
|
||||||
|
check_uuid_url: |
|
||||||
|
The url from Codeharbor where we can check if the exercise already exists. If you don't know what to write here, ask an admin.
|
||||||
name: |
|
name: |
|
||||||
Can be anything to Identify your account link.
|
Can be anything to Identify your account link.
|
||||||
token: |
|
token: |
|
||||||
@ -323,13 +325,12 @@ en:
|
|||||||
exercise_found: A corresponding exercise has been found on Codeocean. You can either <ul><li>Create a new exercise as a duplicate of this one on Codeharbor and push it to Codeocean, using the "Create new" button.</li><li>Overwrite the exercise on Codeocean, by pushing all changes. Only use "Overwrite" for bugfixes or very small changes - it will alter and may break published exercises.</li></ul>
|
exercise_found: A corresponding exercise has been found on Codeocean. You can either <ul><li>Create a new exercise as a duplicate of this one on Codeharbor and push it to Codeocean, using the "Create new" button.</li><li>Overwrite the exercise on Codeocean, by pushing all changes. Only use "Overwrite" for bugfixes or very small changes - it will alter and may break published exercises.</li></ul>
|
||||||
exercise_found_no_right: A corresponding exercise has been found on Codeocean, but you don't have the rights to edit it. You can only <ul><li>Create a new exercise as a duplicate of this one on Codeharbor and push it to Codeocean, using the "Create new" button.</li></ul>
|
exercise_found_no_right: A corresponding exercise has been found on Codeocean, but you don't have the rights to edit it. You can only <ul><li>Create a new exercise as a duplicate of this one on Codeharbor and push it to Codeocean, using the "Create new" button.</li></ul>
|
||||||
export_codeharbor:
|
export_codeharbor:
|
||||||
fail: Failed to push the exercise to CodeHarbor.
|
|
||||||
label: Export to Codeharbor
|
label: Export to Codeharbor
|
||||||
success: Successfully pushed the exercise to CodeHarbor.
|
|
||||||
dialogtitle: Export to Codeharbor
|
dialogtitle: Export to Codeharbor
|
||||||
successfully_exported: 'Exercise has successfully been exported.<br>ID: %{id}<br>Title: %{title}'
|
successfully_exported: 'Exercise has successfully been exported.<br>ID: %{id}<br>Title: %{title}'
|
||||||
export_failed: 'Export has failed.<br>ID: %{id}<br>Title: %{title}<br><br>Error: %{error}'
|
export_failed: 'Export has failed.<br>ID: %{id}<br>Title: %{title}<br><br>Error: %{error}'
|
||||||
error: 'An error occurred while contacting Codeharbor<br>Error: %{message}'
|
error: 'An error occurred while contacting Codeharbor<br>Error: %{message}'
|
||||||
|
checking_codeharbor: Checking whether exercise exists on Codeharbor.
|
||||||
file_form:
|
file_form:
|
||||||
hints:
|
hints:
|
||||||
feedback_message: This message is used as a hint for failing tests.
|
feedback_message: This message is used as a hint for failing tests.
|
||||||
|
@ -85,7 +85,6 @@ Rails.application.routes.draw do
|
|||||||
get :reload
|
get :reload
|
||||||
post :submit
|
post :submit
|
||||||
get 'study_group_dashboard/:study_group_id', to: 'exercises#study_group_dashboard'
|
get 'study_group_dashboard/:study_group_id', to: 'exercises#study_group_dashboard'
|
||||||
post :push_proforma_xml
|
|
||||||
post :export_external_check
|
post :export_external_check
|
||||||
post :export_external_confirm
|
post :export_external_confirm
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
class AddPushUrlRenameOauth2tokenInCodeharborLinks < ActiveRecord::Migration[5.2]
|
class AddPushUrlRenameOauth2tokenInCodeharborLinks < ActiveRecord::Migration[5.2]
|
||||||
def change
|
def change
|
||||||
add_column :codeharbor_links, :push_url, :string
|
add_column :codeharbor_links, :push_url, :string
|
||||||
|
add_column :codeharbor_links, :check_uuid_url, :string
|
||||||
rename_column :codeharbor_links, :oauth2token, :api_key
|
rename_column :codeharbor_links, :oauth2token, :api_key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -34,6 +34,7 @@ ActiveRecord::Schema.define(version: 2019_10_08_163045) do
|
|||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.string "push_url"
|
t.string "push_url"
|
||||||
|
t.string "check_uuid_url"
|
||||||
t.index ["user_id"], name: "index_codeharbor_links_on_user_id"
|
t.index ["user_id"], name: "index_codeharbor_links_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user