Merge branch 'master' into refactor_proforma_import_export

This commit is contained in:
Karol
2022-09-13 22:47:50 +02:00
67 changed files with 1199 additions and 601 deletions

View File

@ -0,0 +1,18 @@
default: &default
default_src: []
development:
<<: *default
# Allow the webpack-dev-server in development
connect_src:
- http://localhost:3035
- ws://localhost:3035
production:
<<: *default
test:
<<: *default

View File

@ -0,0 +1,33 @@
# This file allows to further customize the Content Security Policy (CSP)
# All settings will be applied **in addition** to the application CSP
# Default directives are defined here: `initializers/content_security_policy.rb`
default: &default
# Allow the S3 service hosted by the openHPI Cloud to be used for images
img_src:
- https://s3.xopic.de
- https://*.s3.xopic.de
- https://s3.openhpicloud.de
- https://*.s3.openhpicloud.de
# Webkit didn't consider the WSS scheme as part of 'self', adding it explicitly
# See https://bugs.webkit.org/show_bug.cgi?id=235873
connect_src:
- wss://codeocean.openhpi.de
# Optionally: Specify a custom, non-Sentry URL for reporting CSP violations
# report_uri: https://example.com/csp-report
development:
<<: *default
# Allow the webpack-dev-server in development
connect_src:
- http://localhost:3035
- ws://localhost:3035
production:
<<: *default
test:
<<: *default

View File

@ -38,7 +38,7 @@ Rails.application.configure do
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local
@ -50,6 +50,7 @@ Rails.application.configure do
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
config.ssl_options = {hsts: {preload: true}}
# Include generic and useful information about system operation, but avoid logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII).

View File

@ -1,5 +1,7 @@
# frozen_string_literal: true
require 'active_support/core_ext/integer/time'
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
@ -9,18 +11,15 @@ Rails.application.configure do
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# true: Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
# Eager load code for prometheus exporter
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
# Eager load is also required for the prometheus exporter
config.eager_load = true
# enable web console in staging
config.web_console.development_only = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
# Full error reports as well as caching are disabled.
config.consider_all_requests_local = false
config.action_controller.perform_caching = false
# Raise an error on page load if there are pending migrations.
@ -39,47 +38,50 @@ Rails.application.configure do
# For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
# config.action_dispatch.rack_cache = true
# Disable Rails's static asset server (Apache or nginx will already do this).
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS.
# config.assets.js_compressor = :uglifier
# Compress CSS using a preprocessor.
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Generate digests for assets URLs.
config.assets.digest = true
# Version of your assets, change this if you want to expire all your assets.
config.assets.version = '1.0'
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.asset_host = 'http://assets.example.com'
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local
# Mount Action Cable outside main process or domain.
# config.action_cable.mount_path = nil
# config.action_cable.url = 'wss://example.com/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
config.ssl_options = {hsts: {preload: true}}
# Set to :debug to see everything in the log.
# Include generic and useful information about system operation, but avoid logging too much
# information to avoid inadvertent exposure of personally identifiable information (PII).
config.log_level = :info
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# config.log_tags = [ :subdomain, :uuid, :request_id ]
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = "http://assets.example.com"
# Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "code_ocean_production"
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# config.assets.precompile += %w( search.js )
config.action_mailer.perform_caching = false
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
@ -92,12 +94,46 @@ Rails.application.configure do
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Disable automatic flushing of the log to improve performance.
# config.autoflush_log = false
# Log disallowed deprecations.
config.active_support.disallowed_deprecation = :log
# Tell Active Support which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Use a different logger for distributed setups.
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
if ENV['RAILS_LOG_TO_STDOUT'].present?
logger = ActiveSupport::Logger.new($stdout)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# Inserts middleware to perform automatic connection switching.
# The `database_selector` hash is used to pass options to the DatabaseSelector
# middleware. The `delay` is used to determine how long to wait after a write
# to send a subsequent read to the primary.
#
# The `database_resolver` class is used by the middleware to determine which
# database is appropriate to use based on the time delay.
#
# The `database_resolver_context` class is used by the middleware to set
# timestamps for the last write to the primary. The resolver uses the context
# class timestamps to determine how long to wait before reading from the
# replica.
#
# By default Rails will store a last write timestamp in the session. The
# DatabaseSelector middleware is designed as such you can define your own
# strategy for connection switching and pass that into the middleware through
# these configuration options.
# config.active_record.database_selector = { delay: 2.seconds }
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
end

View File

@ -6,28 +6,57 @@
# For further information see the following documentation
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
# Rails.application.config.content_security_policy do |policy|
# # If you are using webpack-dev-server then specify webpack-dev-server host
# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
require_relative 'sentry_csp'
require_relative 'sentry_javascript'
# policy.default_src :self, :https
# policy.font_src :self, :https, :data
# policy.img_src :self, :https, :data
# policy.object_src :none
# policy.script_src :self, :https
# policy.style_src :self, :https
# # If you are using webpack-dev-server then specify webpack-dev-server host
# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
def self.apply_yml_settings_for(policy)
csp_settings = CodeOcean::Config.new(:content_security_policy)
# # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint"
# end
csp_settings.read.each do |directive, additional_settings|
existing_settings = if directive == 'report_uri'
''
else
policy.public_send(directive) || []
end
all_settings = existing_settings + additional_settings
policy.public_send(directive, *all_settings)
end
end
def self.apply_sentry_settings_for(policy)
sentry_domain = URI.parse SentryJavascript.dsn
additional_setting = "#{sentry_domain.scheme}://#{sentry_domain.host}"
existing_settings = policy.connect_src || []
all_settings = existing_settings + [additional_setting]
policy.connect_src(*all_settings)
end
Rails.application.config.content_security_policy do |policy|
policy.default_src :none
policy.base_uri :self
policy.font_src :self
# Code executions might return a base64 encoded image as a :data URI
policy.img_src :self, :data
policy.object_src :none
policy.script_src :self, :report_sample
# Our ACE editor unfortunately requires :unsafe_inline for the code highlighting
policy.style_src :self, :unsafe_inline, :report_sample
policy.connect_src :self
policy.form_action :self
policy.frame_ancestors :none
# Specify URI for violation reports
policy.report_uri SentryCsp.report_url if SentryCsp.active?
apply_yml_settings_for policy
apply_sentry_settings_for policy if SentryJavascript.active?
end
# If you are using UJS then enable automatic nonce generation
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
Rails.application.config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
# Set the nonce only to specific directives
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
Rails.application.config.content_security_policy_nonce_directives = %w[script-src]
# Report CSP violations to a specified URI
# For further information see the following documentation:

View File

@ -1,12 +1,26 @@
# frozen_string_literal: true
# Define an application-wide HTTP permissions policy. For further
# information see https://developers.google.com/web/updates/2018/06/feature-policy
#
# Rails.application.config.permissions_policy do |f|
# f.camera :none
# f.gyroscope :none
# f.microphone :none
# f.usb :none
# f.fullscreen :self
# f.payment :self, "https://secure.example.com"
# end
# TODO: Feature-Policy has been renamed to Permissions-Policy. The Permissions-Policy is
# not yet supported by Rails (even though the new name is already used for the method)
Rails.application.config.permissions_policy do |policy|
policy.accelerometer :none
policy.ambient_light_sensor :none
policy.autoplay :none
policy.camera :none
policy.encrypted_media :none
policy.fullscreen :none
policy.geolocation :none
policy.gyroscope :none
policy.magnetometer :none
policy.microphone :none
policy.midi :none
policy.payment :none
policy.picture_in_picture :none
# The `speaker` directive is used for selection of non-default audio output devices
policy.speaker :none
policy.usb :none
policy.vibrate :none
policy.vr :none
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
require_relative 'sentry'
class SentryCsp
def self.active?
dsn.present? && %w[development test].exclude?(environment)
end
def self.report_url
parsed_url = URI.parse dsn
# Add additional variables to the query string
query_params = CGI.parse(parsed_url.query || '')
query_params[:sentry_release] = release if release
query_params[:sentry_environment] = environment if environment
# Add the query string back to the URL
parsed_url.query = URI.encode_www_form(query_params)
# Return the full URL
parsed_url.to_s
end
class << self
private
def dsn
ENV.fetch('SENTRY_CSP_REPORT_URL', nil)
end
def release
Sentry.configuration.release
end
def environment
Sentry.configuration.environment
end
end
end

View File

@ -1,5 +1,7 @@
# frozen_string_literal: true
require_relative 'sentry'
class SentryJavascript
def self.active?
dsn.present? && %w[development test].exclude?(environment)

View File

@ -2,8 +2,23 @@
# Be sure to restart your server when you modify this file.
def self.cookie_prefix
if (Rails.env.production? || Rails.env.staging?) \
&& Rails.application.config.relative_url_root == '/'
'__Host-'
elsif Rails.env.production? || Rails.env.staging?
'__Secure-'
else
''
end
end
Rails.application.config.session_store :cookie_store,
key: '_code_ocean_session',
key: "#{cookie_prefix}CodeOcean-Session",
expire_after: 1.month,
secure: Rails.env.production? || Rails.env.staging?,
path: Rails.application.config.relative_url_root
path: Rails.application.config.relative_url_root,
# Signing in through LTI won't work with `SameSite=Strict`
# as the cookie is not sent when accessing the `implement` route
# following the LTI launch initiated by the LMS as a third party.
same_site: :lax

View File

@ -296,7 +296,7 @@ de:
form:
hints:
command: <em>filename</em> wird automatisch durch den richtigen Dateinamen ersetzt.
docker_image: 'Wählen Sie ein Docker-Image aus der Liste oder fügen Sie ein neues hinzu, welches über <a href="https://hub.docker.com/" target="_blank">DockerHub</a> verfügbar ist.'
docker_image: 'Wählen Sie ein Docker-Image aus der Liste oder fügen Sie ein neues hinzu, welches über <a href="https://hub.docker.com/" target="_blank" rel="noopener">DockerHub</a> verfügbar ist.'
exposed_ports_list: Während der Ausführung sind diese Ports für den Nutzer zugänglich. Die Portnummern müssen nummerisch und mit Komma voneinander getrennt sein.
cpu_limit: Geben Sie die Mindestmenge an CPU-Anteilen an, die für jeden Runner reserviert werden soll, gemessen in MHz.
errors:
@ -340,7 +340,7 @@ de:
expand_output_sidebar: Ausgabe-Leiste Ausklappen
input: Ihre Eingabe
lastsaved: 'Zuletzt gespeichert: '
network: 'Während Ihr Code läuft, ist Port %{port} unter folgender Adresse erreichbar: <a href="%{address}" target="_blank">%{address}</a>.'
network: 'Während Ihr Code läuft, ist Port %{port} unter folgender Adresse erreichbar: <a href="%{address}" target="_blank" rel="noopener">%{address}</a>.'
render: Anzeigen
run: Ausführen
run_failure: Ihr Code konnte nicht auf der Plattform ausgeführt werden.
@ -453,7 +453,7 @@ de:
request: "Kommentaranfrage stellen"
question: "Bitte beschreiben Sie kurz Ihre Probleme oder nennen Sie den Programmteil, zu dem Sie Feedback wünschen. Ihr Programmcode und eventuelle Fehlermeldungen werden automatisch zur Anfrage hinzugefügt."
intervention:
explanation: "Diese Meldung erscheint, weil Sie %{duration} Minuten an dieser Aufgabe gearbeitet haben. 25% Ihrer Mitlernenden arbeiten länger daran, insofern ist das kein Problem, aber dies hat sich als <a href='https://hpi.de/forschung/publikationen/dissertationen/dissertation-ralf-teusner.html' style='display: contents;'>effektiven Zeitpunkt für diese Meldung</a> erwiesen."
explanation: "Diese Meldung erscheint, weil Sie %{duration} Minuten an dieser Aufgabe gearbeitet haben. 25% Ihrer Mitlernenden arbeiten länger daran, insofern ist das kein Problem, aber dies hat sich als <a href='https://hpi.de/forschung/publikationen/dissertationen/dissertation-ralf-teusner.html' style='display: contents;' target='_blank' rel='noopener'>effektiven Zeitpunkt für diese Meldung</a> erwiesen."
rfc_intervention:
text: "Falls Sie bei dieser Aufgabe nicht weiterkommen und nicht selbst weiter knobeln möchten, können Ihre Mitlernenden bestimmt helfen! </br> </br>"
break_intervention:
@ -780,7 +780,7 @@ de:
runtime_output: "Programmausgabe"
test_results: "Testergebnisse"
sessions:
expired: Ihre Session ist abgelaufen. Bitte <a href="javascript:window.location.reload(true)">laden Sie diese Seite neu</a> bevor Sie fortfahren.
expired: Ihre Session ist abgelaufen. Bitte <a href="" class="reloadCurrentPage">laden Sie diese Seite neu</a> bevor Sie fortfahren.
create:
failure: Fehlerhafte E-Mail oder Passwort.
success: Sie haben sich erfolgreich angemeldet.
@ -793,7 +793,7 @@ de:
destroy_through_lti:
average_score: Durchschnittliche Punktzahl
final_submissions: Abgaben anderer Nutzer
finished_with_consumer: 'Sie können dieses Fenster nun schließen oder <a href="%{url}">zu %{consumer} zurückkehren</a>.'
finished_with_consumer: 'Sie können dieses Fenster nun schließen oder <a href="%{url}" rel="nofollow">zu %{consumer} zurückkehren</a>.'
finished_without_consumer: Sie können dieses Fenster nun schließen.
headline: Gut gemacht!
score: Ihre Punktzahl
@ -834,7 +834,7 @@ de:
link: Hilfe
index: Index
message_failure: Leider ist ein Fehler auf unserer Plattform aufgetreten. Bitte probieren Sie es später noch einmal.
websocket_failure: Leider ist ein Verbindungsproblem aufgetreten. <a href="https://websocketstest.com">Bitte überprüfen Sie Websocket-Verbindungen mit diesem Tool</a> und versuchen Sie es erneut.
websocket_failure: Leider ist ein Verbindungsproblem aufgetreten. <a href="https://websocketstest.com" target="_blank" rel="noopener">Bitte überprüfen Sie Websocket-Verbindungen mit diesem Tool</a> und versuchen Sie es erneut.
new: Hinzufügen
new_model: '%{model} hinzufügen'
number: Nummer

View File

@ -296,7 +296,7 @@ en:
form:
hints:
command: <em>filename</em> is automatically replaced with the correct filename.
docker_image: Pick a Docker image listed above or add a new one which is available via <a href="https://hub.docker.com/" target="_blank">DockerHub</a>.
docker_image: Pick a Docker image listed above or add a new one which is available via <a href="https://hub.docker.com/" target="_blank" rel="noopener">DockerHub</a>.
exposed_ports_list: During code execution these ports are accessible for the user. Port numbers must be numeric and separated by a comma.
cpu_limit: Specify the minimum amount of CPU shares to reserve for each runner, measured in MHz.
errors:
@ -340,7 +340,7 @@ en:
expand_output_sidebar: Expand Output Sidebar
input: Your input
lastsaved: 'Last saved: '
network: 'While your code is running, port %{port} is accessible using the following address: <a href="%{address}" target="_blank">%{address}</a>.'
network: 'While your code is running, port %{port} is accessible using the following address: <a href="%{address}" target="_blank" rel="noopener">%{address}</a>.'
render: Render
run: Run
run_failure: Your code could not be run.
@ -453,7 +453,7 @@ en:
request: "Request Comments"
question: 'Please shortly describe your problem or the program part you would like to get feedback for. Your program code and potential error messages are automatically appended to your request.'
intervention:
explanation: "This message appears because you have been working on this exercise for %{duration} minutes. 25% of your fellow learners took more time to solve the exercise, so in that sense it's not a problem, but this has proven to be an <a href='https://hpi.de/en/research/publications/dissertations/dissertation-ralf-teusner.html' style='display: contents;'>effective time for this message</a>."
explanation: "This message appears because you have been working on this exercise for %{duration} minutes. 25% of your fellow learners took more time to solve the exercise, so in that sense it's not a problem, but this has proven to be an <a href='https://hpi.de/en/research/publications/dissertations/dissertation-ralf-teusner.html' style='display: contents;' target='_blank' rel='noopener'>effective time for this message</a>."
rfc_intervention:
text: "If you are struggling with this exercise and don't want to continue on your own, your fellow learners can help out! </br> </br>"
break_intervention:
@ -780,7 +780,7 @@ en:
runtime_output: "Runtime Output"
test_results: "Test Results"
sessions:
expired: Your session has expired. Please <a href="javascript:window.location.reload(true)">reload this page</a> before continuing.
expired: Your session has expired. Please <a href="" class="reloadCurrentPage">reload this page</a> before continuing.
create:
failure: Invalid email or password.
success: Successfully signed in.
@ -793,7 +793,7 @@ en:
destroy_through_lti:
average_score: Average Score
final_submissions: Other Users' Submissions
finished_with_consumer: 'You may close this window now or <a href="%{url}">return to %{consumer}</a>.'
finished_with_consumer: 'You may close this window now or <a href="%{url}" rel="nofollow">return to %{consumer}</a>.'
finished_without_consumer: You may close this window now.
headline: Well done!
score: Your Score
@ -834,7 +834,7 @@ en:
link: Help
index: Index
message_failure: 'Sorry, something went wrong.'
websocket_failure: Sorry, a connection issue occoured. <a href="https://websocketstest.com">Please check WebSocket connections with this tool</a> and try again.
websocket_failure: Sorry, a connection issue occoured. <a href="https://websocketstest.com" target="_blank" rel="noopener">Please check WebSocket connections with this tool</a> and try again.
new: Add
new_model: 'Add %{model}'
number: Number

View File

@ -128,6 +128,7 @@ Rails.application.routes.draw do
namespace :code_ocean do
resources :files, only: %i[create destroy]
end
get '/uploads/files/:id/:filename', to: 'code_ocean/files#show_protected_upload', as: :protected_upload, constraints: {filename: FILENAME_REGEXP}
resources :file_types

View File

@ -1,12 +1,14 @@
// See the shakacode/shakapacker README and docs directory for advice on customizing your webpackConfig.
const { webpackConfig, merge } = require('shakapacker')
const { webpackConfig, config, merge } = require('shakapacker')
const webpack = require('webpack');
const CompressionPlugin = require("compression-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const WebpackAssetsManifest = require('webpack-assets-manifest');
const { SubresourceIntegrityPlugin } = require("webpack-subresource-integrity");
// Custom ERB loader to disable Spring and prevent crashes
const erb = require("./loaders/erb");
@ -30,7 +32,9 @@ const envConfig = module.exports = {
],
},
output: {
publicPath: relative_url_root + public_output_path
publicPath: relative_url_root + public_output_path,
// the following setting is required for SRI to work:
crossOriginLoading: 'anonymous',
},
performance: {
// Turn off size warnings for large assets
@ -53,6 +57,15 @@ const envConfig = module.exports = {
}),
new CompressionPlugin(),
new MiniCssExtractPlugin(),
new SubresourceIntegrityPlugin(),
new WebpackAssetsManifest({
entrypoints: true,
integrity: false,
writeToDisk: true,
entrypointsUseAssets: true,
publicPath: true,
output: config.manifestPath,
})
],
resolve: {
extensions: ['.css', '.ts', '.tsx'],
@ -65,4 +78,8 @@ const envConfig = module.exports = {
stats: 'minimal',
}
// Use the two lines below to remove the original WebpackAssetsManifest and replace it with our custom config.
const filteredPlugins = webpackConfig.plugins.filter((plugin) => !(plugin instanceof WebpackAssetsManifest))
webpackConfig.plugins = filteredPlugins;
module.exports = merge(webpackConfig, envConfig)