diff --git a/.cursorrules b/.cursorrules index e8448424..0a1ade25 100644 --- a/.cursorrules +++ b/.cursorrules @@ -59,3 +59,6 @@ - Protect against common web vulnerabilities (XSS, CSRF, SQL injection). Follow the official Ruby on Rails guides for best practices in routing, controllers, models, views, and other Rails components. + +I approach code architecture through domain modeling first. +I am a visual learner, I find analogies particularly helpful. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d87f1501..365fc913 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,91 @@ -@rsmoke +# CODEOWNERS file for lsa_evaluate +# Each line is a file pattern followed by one or more owners. +# Order is important; the last matching pattern takes precedence. + +# Default owners for everything in the repo +* @rsmoke + +################################################# +# Repository Configuration +################################################# + +# GitHub specific files and workflows /.github/ @rsmoke + +# Configuration files +/config/ @rsmoke +/.ruby-version @rsmoke +/.tool-versions @rsmoke +/.rubocop.yml @rsmoke +/.rspec @rsmoke +/.gitattributes @rsmoke +/.gitignore @rsmoke +/.babelrc @rsmoke +/jest.config.js @rsmoke +/Capfile @rsmoke +/Procfile.dev @rsmoke +/Rakefile @rsmoke +/config.ru @rsmoke + +# Dependency management +/Gemfile @rsmoke +/Gemfile.lock @rsmoke +/package.json @rsmoke +/yarn.lock @rsmoke + +################################################# +# Application Code +################################################# + +# Core application code +/app/ @rsmoke + +# MVC Components +/app/models/ @rsmoke +/app/views/ @rsmoke +/app/controllers/ @rsmoke + +# Frontend assets +/app/assets/ @rsmoke +/app/javascript/ @rsmoke + +# Additional application components +/app/helpers/ @rsmoke +/app/mailers/ @rsmoke +/app/jobs/ @rsmoke +/app/channels/ @rsmoke +/app/policies/ @rsmoke +/app/services/ @rsmoke +/app/forms/ @rsmoke +/app/inputs/ @rsmoke + +# Database related files +/db/ @rsmoke + +# Library code +/lib/ @rsmoke +/lib/tasks/ @rsmoke +/lib/capistrano/ @rsmoke + +################################################# +# Testing and Documentation +################################################# + +# Test files +/spec/ @rsmoke + +# Documentation +*.md @rsmoke +/LICENSE @rsmoke + +################################################# +# Public and Binary Files +################################################# + +# Public files +/public/ @rsmoke + +# Binary and storage directories +/bin/ @rsmoke +/vendor/ @rsmoke +/storage/ @rsmoke diff --git a/Gemfile.lock b/Gemfile.lock index eebb3903..dd912d48 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -268,9 +268,9 @@ GEM net-protocol net-ssh (7.2.3) nio4r (2.7.3) - nokogiri (1.17.1-arm64-darwin) + nokogiri (1.18.3-arm64-darwin) racc (~> 1.4) - nokogiri (1.17.1-x86_64-linux) + nokogiri (1.18.3-x86_64-linux-gnu) racc (~> 1.4) omniauth (2.1.2) hashie (>= 3.4.6) diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index 31e12704..b753de56 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -4,8 +4,10 @@ module Users # The `OmniauthCallbacksController` class is responsible for handling callbacks from OmniAuth providers. # It inherits from the `Devise::OmniauthCallbacksController` class, which is provided by the Devise gem. class OmniauthCallbacksController < Devise::OmniauthCallbacksController - skip_before_action :verify_authenticity_token, only: :saml + # Instead of disabling CSRF protection, we'll configure it to work with SAML + protect_from_forgery with: :exception, except: :saml before_action :set_user, only: :saml + attr_reader :user, :service def saml diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 185a61c8..ffdce7e3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -18,7 +18,7 @@ def render_editable_content(page, section) safe_join([ content_html, edit_link ], ' ').html_safe else # If the user doesn't have the role, just render the content - content_html.html_safe + html_escape(content_html) end end diff --git a/app/views/contest_instances/_manage_judges.html.erb b/app/views/contest_instances/_manage_judges.html.erb index 2d572f4a..22195a9d 100644 --- a/app/views/contest_instances/_manage_judges.html.erb +++ b/app/views/contest_instances/_manage_judges.html.erb @@ -46,6 +46,34 @@ +
Internal: + <%= round.require_internal_comments ? 'Required' : 'Optional' %> + <% if round.require_internal_comments && round.min_internal_comment_words > 0 %> + (minimum <%= pluralize(round.min_internal_comment_words, 'word') %>) + <% end %> +
+External: + <%= round.require_external_comments ? 'Required' : 'Optional' %> + <% if round.require_external_comments && round.min_external_comment_words > 0 %> + (minimum <%= pluralize(round.min_external_comment_words, 'word') %>) + <% end %> +
+Internal: + <%= round.require_internal_comments ? 'Required' : 'Optional' %> + <% if round.require_internal_comments && round.min_internal_comment_words > 0 %> + (minimum <%= pluralize(round.min_internal_comment_words, 'word') %>) + <% end %> +
+External: + <%= round.require_external_comments ? 'Required' : 'Optional' %> + <% if round.require_external_comments && round.min_external_comment_words > 0 %> + (minimum <%= pluralize(round.min_external_comment_words, 'word') %>) + <% end %> +
+End Date for judging round: <%= format_datetime(@judging_round.end_date) %>
Internal Comments: <%= @judging_round.require_internal_comments ? 'Required' : 'Optional' %> diff --git a/config/application.rb b/config/application.rb index 52916493..5d48da55 100644 --- a/config/application.rb +++ b/config/application.rb @@ -29,6 +29,11 @@ class Application < Rails::Application # rubocop:disable Style/Documentation config.time_zone = 'Eastern Time (US & Canada)' config.active_record.default_timezone = :utc config.exceptions_app = self.routes + + # Configure CSRF protection to work with OmniAuth SAML + # This allows SAML callbacks to work properly without disabling CSRF protection + config.action_controller.forgery_protection_origin_check = false + # Configuration for the application, engines, and railties goes here. # # These settings can be overridden in specific environments using the files diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index a660b46d..32c84065 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -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--4/JCz6FVMP1MsiEf--fekOMtClLRvJAl57QLuPgQ== \ No newline at end of file +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--rd03KodkgSwMYUQQ--ypiBs1SjXFkb7Cu78I4+JQ== \ No newline at end of file diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 00000000..b371f887 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Configure OmniAuth to work properly with CSRF protection +# This is needed because the omniauth-rails_csrf_protection gem requires +# proper configuration to work with SAML callbacks + +# Set the full_host for OmniAuth to ensure proper callback URLs +OmniAuth.config.full_host = lambda do |env| + scheme = env['rack.url_scheme'] + host = env['HTTP_HOST'] || env['SERVER_NAME'] || env['SERVER_ADDR'] + port = env['SERVER_PORT'] + + port = nil if (scheme == 'https' && port == '443') || (scheme == 'http' && port == '80') + + if port + "#{scheme}://#{host}:#{port}" + else + "#{scheme}://#{host}" + end +end + +# Configure OmniAuth to use a custom request phase for SAML +# This helps with CSRF protection while still allowing SAML callbacks to work +OmniAuth.config.request_validation_phase = lambda do |env| + # Skip CSRF validation for SAML callbacks + if env['PATH_INFO'] =~ %r{/auth/saml/callback} + # Still perform other validations if needed + # But skip CSRF token validation + else + # For all other OmniAuth paths, use the default CSRF protection + OmniAuth::RailsCsrfProtection::TokenVerifier.new.call(env) + end +end + +# Set a custom path prefix for OmniAuth +# This is optional but can be useful for routing +OmniAuth.config.path_prefix = '/users/auth' diff --git a/config/skylight.yml b/config/skylight.yml index 1b663428..624dda7b 100644 --- a/config/skylight.yml +++ b/config/skylight.yml @@ -1,3 +1,5 @@ ---- -# The authentication token for the application. -authentication: <%= Rails.application.credentials.dig(:skylight, :authentication) %> +deploy: + id: <%= ENV["HATCHBOX_RELEASE"] %> + git_sha: <%= ENV["HATCHBOX_REVISION"] %> + # The deploy description is optional. + description: "Deployed <%= ENV["HATCHBOX_REVISION"] %> on <%= Rails.env %>" diff --git a/yarn.lock b/yarn.lock index fd8a57d5..1753922a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2001,9 +2001,9 @@ domexception@^4.0.0: webidl-conversions "^7.0.0" dompurify@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.3.tgz#05dd2175225324daabfca6603055a09b2382a4cd" - integrity sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA== + version "3.2.4" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.4.tgz#af5a5a11407524431456cf18836c55d13441cd8e" + integrity sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg== optionalDependencies: "@types/trusted-types" "^2.0.7"