From 21e0713f10a5cd4dc94c4ac369a9d2f5e80f60f0 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:00:05 +1000 Subject: [PATCH 1/3] chore: update gems --- Gemfile.lock | 608 ++++++++++++++++++++++++++++----------------------- 1 file changed, 335 insertions(+), 273 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9df7ab4c0..952ddff75 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,29 +2,31 @@ GEM remote: https://rubygems.org/ specs: Ascii85 (2.0.1) - actioncable (8.0.2) - actionpack (= 8.0.2) - activesupport (= 8.0.2) + action_text-trix (2.1.19) + railties + actioncable (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (8.0.2) - actionpack (= 8.0.2) - activejob (= 8.0.2) - activerecord (= 8.0.2) - activestorage (= 8.0.2) - activesupport (= 8.0.2) + actionmailbox (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) mail (>= 2.8.0) - actionmailer (8.0.2) - actionpack (= 8.0.2) - actionview (= 8.0.2) - activejob (= 8.0.2) - activesupport (= 8.0.2) + actionmailer (8.1.3) + actionpack (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activesupport (= 8.1.3) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.0.2) - actionview (= 8.0.2) - activesupport (= 8.0.2) + actionpack (8.1.3) + actionview (= 8.1.3) + activesupport (= 8.1.3) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -32,64 +34,69 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (8.0.2) - actionpack (= 8.0.2) - activerecord (= 8.0.2) - activestorage (= 8.0.2) - activesupport (= 8.0.2) + actiontext (8.1.3) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (8.0.2) - activesupport (= 8.0.2) + actionview (8.1.3) + activesupport (= 8.1.3) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.0.2) - activesupport (= 8.0.2) + activejob (8.1.3) + activesupport (= 8.1.3) globalid (>= 0.3.6) - activemodel (8.0.2) - activesupport (= 8.0.2) - activerecord (8.0.2) - activemodel (= 8.0.2) - activesupport (= 8.0.2) + activemodel (8.1.3) + activesupport (= 8.1.3) + activerecord (8.1.3) + activemodel (= 8.1.3) + activesupport (= 8.1.3) timeout (>= 0.4.0) - activestorage (8.0.2) - actionpack (= 8.0.2) - activejob (= 8.0.2) - activerecord (= 8.0.2) - activesupport (= 8.0.2) + activestorage (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activesupport (= 8.1.3) marcel (~> 1.0) - activesupport (8.0.2) + activesupport (8.1.3) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) tzinfo (~> 2.0, >= 2.0.5) uri (>= 0.13.1) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) + addressable (2.9.0) + public_suffix (>= 2.0.2, < 8.0) aes_key_wrap (1.1.0) - afm (0.2.2) - amq-protocol (2.3.3) + afm (1.0.0) + amq-protocol (2.8.0) + anonymous_loader (0.1.3) + version_gem (~> 1.1, >= 1.1.14) ast (2.4.3) + auth-sanitizer (0.2.3) + version_gem (~> 1.1, >= 1.1.14) backport (1.2.0) - base64 (0.2.0) - bcrypt (3.1.20) - benchmark (0.4.0) + base64 (0.3.0) + bcrypt (3.1.22) + benchmark (0.5.0) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) rouge (>= 1.0.0) - bigdecimal (3.1.9) - bindata (2.5.0) - bootsnap (1.18.4) + bigdecimal (3.3.1) + bindata (3.0.0) + bootsnap (1.24.6) msgpack (~> 1.2) builder (3.3.0) bunny (2.24.0) @@ -97,7 +104,8 @@ GEM sorted_set (~> 1, >= 1.0.2) bunny-pub-sub (0.5.2) bunny (~> 2.14) - byebug (12.0.0) + byebug (13.0.0) + reline (>= 0.6.0) chronic_duration (0.10.6) numerizer (~> 0.1.1) ci_reporter (2.1.0) @@ -106,171 +114,192 @@ GEM code_analyzer (0.5.5) sexp_processor coderay (1.1.3) - concurrent-ruby (1.3.5) - connection_pool (2.5.0) - crack (1.0.0) + commander (5.0.0) + highline (~> 3.0.0) + concurrent-ruby (1.3.8) + connection_pool (3.0.2) + crack (1.0.1) bigdecimal rexml - crass (1.0.6) + crass (1.0.7) cronex (0.15.0) tzinfo unicode (>= 0.4.4.5) - csv (3.3.3) - database_cleaner-active_record (2.2.0) + csv (3.3.6) + database_cleaner-active_record (2.2.2) activerecord (>= 5.a) - database_cleaner-core (~> 2.0.0) - database_cleaner-core (2.0.1) - date (3.4.1) - devise (4.9.4) + database_cleaner-core (~> 2.0) + database_cleaner-core (2.1.0) + date (3.5.1) + devise (5.0.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0) + railties (>= 7.0) responders warden (~> 1.2.3) devise_ldap_authenticatable (0.8.7) devise (>= 3.4.1) net-ldap (>= 0.16.0) - diff-lcs (1.6.1) - docile (1.4.1) + diff-lcs (1.6.2) domain_name (0.6.20240107) - dotenv (3.1.7) - drb (2.2.1) - dry-core (1.1.0) + dotenv (3.2.0) + drb (2.2.3) + dry-configurable (1.4.0) + dry-core (~> 1.0) + zeitwerk (~> 2.6) + dry-core (1.2.0) concurrent-ruby (~> 1.0) logger zeitwerk (~> 2.6) - dry-inflector (1.2.0) + dry-inflector (1.3.1) dry-logic (1.6.0) bigdecimal concurrent-ruby (~> 1.0) dry-core (~> 1.1) zeitwerk (~> 2.6) - dry-types (1.8.2) - bigdecimal (~> 3.0) + dry-types (1.9.1) + bigdecimal (>= 3.0) concurrent-ruby (~> 1.0) dry-core (~> 1.0) dry-inflector (~> 1.0) dry-logic (~> 1.4) zeitwerk (~> 2.6) + erb (6.0.6) erubi (1.13.1) erubis (2.7.0) - et-orbi (1.2.11) + et-orbi (1.4.0) tzinfo - ethon (0.16.0) + ethon (0.18.0) ffi (>= 1.15.0) - factory_bot (6.5.1) + logger + factory_bot (6.6.0) activesupport (>= 6.1.0) - factory_bot_rails (6.4.4) + factory_bot_rails (6.5.1) factory_bot (~> 6.5) - railties (>= 5.0.0) - faker (3.5.1) + railties (>= 6.1.0) + faker (3.8.0) i18n (>= 1.8.11, < 2) - faraday (2.12.2) + faraday (2.14.3) faraday-net_http (>= 2.0, < 3.5) json logger - faraday-follow_redirects (0.3.0) + faraday-follow_redirects (0.5.0) faraday (>= 1, < 3) - faraday-net_http (3.4.0) - net-http (>= 0.5.0) - ffi (1.17.1-aarch64-linux-gnu) - ffi (1.17.1-x86_64-linux-gnu) - fugit (1.11.1) - et-orbi (~> 1, >= 1.2.11) + faraday-net_http (3.4.4) + net-http (~> 0.5) + ffi (1.17.4-aarch64-linux-gnu) + ffi (1.17.4-x86_64-linux-gnu) + fugit (1.13.0) + et-orbi (~> 1.4) raabro (~> 1.4) - globalid (1.2.1) + globalid (1.4.0) activesupport (>= 6.1) - grape (2.3.0) - activesupport (>= 6) + grape (3.3.4) + activesupport (>= 7.2) + dry-configurable (>= 1.0) dry-types (>= 1.1) - mustermann-grape (~> 1.1.0) - rack (>= 2) - zeitwerk - grape-entity (1.0.1) + mustermann (>= 4.0) + rack (>= 2.2.4) + zeitwerk (>= 2.6) + grape-entity (1.1.0) activesupport (>= 3.0.0) - multi_json (>= 1.3.2) - grape-swagger (2.1.2) - grape (>= 1.7, < 3.0) - rack-test (~> 2) - grape-swagger-rails (0.6.0) - ostruct - railties (>= 6.0.6.1) - hashdiff (1.1.2) + grape-swagger (2.1.4) + grape (>= 1.7, < 4.0) + grape-swagger-rails (1.0.5) + haml-rails (>= 2.0, < 4.0) + ostruct (>= 0.6, < 1.0) + railties (>= 7.2.2.2, < 8.2) + haml (7.2.2) + temple (>= 0.8.2) + thor + tilt + haml-rails (3.1.0) + actionpack (>= 5.1) + activesupport (>= 5.1) + haml (>= 4.0.6) + railties (>= 5.1) + hashdiff (1.2.1) hashery (2.1.2) - hashie (5.0.0) + hashie (5.1.0) + logger + highline (3.0.1) hirb (0.7.3) http-accept (1.7.0) - http-cookie (1.0.8) + http-cookie (1.1.6) domain_name (~> 0.5) - i18n (1.14.7) + i18n (1.15.2) concurrent-ruby (~> 1.0) - icalendar (2.10.3) + icalendar (2.12.3) + base64 ice_cube (~> 0.16) + logger ostruct ice_cube (0.17.0) - io-console (0.8.0) - irb (1.15.1) + io-console (0.8.2) + irb (1.18.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - jaro_winkler (1.6.0) - json (2.10.2) - json-jwt (1.16.7) + jaro_winkler (1.7.0) + json (2.21.1) + json-jwt (1.17.1) activesupport (>= 4.2) aes_key_wrap base64 bindata faraday (~> 2.0) faraday-follow_redirects - jwt (2.10.1) + jwt (3.2.0) base64 - kramdown (2.5.1) - rexml (>= 3.3.9) + kramdown (2.5.2) + rexml (>= 3.4.4) kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) - language_server-protocol (3.17.0.4) + language_server-protocol (3.17.0.6) lint_roller (1.1.0) - listen (3.9.0) + listen (3.10.0) + logger rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) logger (1.7.0) - loofah (2.24.0) + loofah (2.25.2) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mail (2.8.1) + mail (2.9.1) + logger mini_mime (>= 0.1.1) net-imap net-pop net-smtp - marcel (1.0.4) - mime-types (3.6.2) + marcel (1.2.1) + mime-types (3.7.0) logger - mime-types-data (~> 3.2015) - mime-types-data (3.2025.0325) + mime-types-data (~> 3.2025, >= 3.2025.0507) + mime-types-data (3.2026.0701) mini_mime (1.1.5) - minitest (5.25.5) - minitest-around (0.5.0) - minitest (~> 5.0) - minitest-rails (8.0.0) + minitest (5.27.0) + minitest-around (0.6.0) + minitest (> 5.0, < 7.0) + minitest-rails (8.1.0) minitest (~> 5.20) - railties (>= 8.0.0, < 8.1.0) + railties (>= 8.1.0, < 8.2.0) moss_ruby (1.1.4) tcp_timeout (~> 0.1.1) - msgpack (1.8.0) - multi_json (1.15.0) - multi_xml (0.7.1) - bigdecimal (~> 3.1) - mustermann (3.0.3) - ruby2_keywords (~> 0.0.1) - mustermann-grape (1.1.0) - mustermann (>= 1.0.0) - mysql2 (0.5.6) - net-http (0.6.0) - uri - net-imap (0.5.6) + msgpack (1.8.4) + multi_xml (0.9.1) + bigdecimal (>= 3.1, < 5) + mustermann (4.0.0) + mysql2 (0.5.7) + bigdecimal + net-http (0.9.1) + uri (>= 0.11.1) + net-imap (0.6.6) date net-protocol - net-ldap (0.19.0) + net-ldap (0.20.0) + base64 + ostruct net-pop (0.1.2) net-protocol net-protocol (0.2.2) @@ -278,291 +307,324 @@ GEM net-smtp (0.5.1) net-protocol netrc (0.11.0) - nio4r (2.7.4) - nokogiri (1.18.7-aarch64-linux-gnu) + nio4r (2.7.5) + nokogiri (1.19.4-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.18.7-x86_64-linux-gnu) + nokogiri (1.19.4-x86_64-linux-gnu) racc (~> 1.4) numerizer (0.1.1) - oauth2 (2.0.9) - faraday (>= 0.17.3, < 3.0) - jwt (>= 1.0, < 3.0) + oauth2 (2.0.25) + anonymous_loader (~> 0.1, >= 0.1.3) + auth-sanitizer (~> 0.2, >= 0.2.3) + faraday (>= 0.17.3, < 4.0) + jwt (>= 1.0, < 4.0) + logger (~> 1.2) multi_xml (~> 0.5) rack (>= 1.2, < 4) - snaky_hash (~> 2.0) - version_gem (~> 1.1) + snaky_hash (~> 2.0, >= 2.0.7) + version_gem (~> 1.1, >= 1.1.14) observer (0.1.2) + open3 (0.2.1) orm_adapter (0.5.0) - ostruct (0.6.1) - parallel (1.26.3) - parser (3.3.7.4) + ostruct (0.6.3) + parallel (2.1.0) + parlour (9.1.2) + commander (~> 5.0) + parser + rainbow (~> 3.0) + sorbet-runtime (>= 0.5) + parser (3.3.12.0) ast (~> 2.4.1) racc - pdf-reader (2.14.1) + pdf-reader (2.15.1) Ascii85 (>= 1.0, < 3.0, != 2.0.0) - afm (~> 0.2.1) + afm (>= 0.2.1, < 2) hashery (~> 2.0) ruby-rc4 ttfunk - pkg-config (1.6.0) - pp (0.6.2) + pkg-config (1.6.5) + pp (0.6.4) prettyprint prettyprint (0.2.0) - prism (1.4.0) - psych (5.2.3) + prism (1.9.0) + psych (5.4.0) date stringio - public_suffix (6.0.1) - puma (6.6.0) + public_suffix (7.0.5) + puma (8.0.2) nio4r (~> 2.0) - raabro (1.4.0) + raabro (1.5.0) racc (1.8.1) - rack (3.1.12) - rack-cors (2.0.2) - rack (>= 2.0.0) - rack-session (2.1.0) + rack (3.2.6) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) + rack-session (2.1.2) base64 (>= 0.1.0) rack (>= 3.0.0) rack-test (2.2.0) rack (>= 1.3) - rackup (2.2.1) + rackup (2.3.1) rack (>= 3) - rails (8.0.2) - actioncable (= 8.0.2) - actionmailbox (= 8.0.2) - actionmailer (= 8.0.2) - actionpack (= 8.0.2) - actiontext (= 8.0.2) - actionview (= 8.0.2) - activejob (= 8.0.2) - activemodel (= 8.0.2) - activerecord (= 8.0.2) - activestorage (= 8.0.2) - activesupport (= 8.0.2) + rails (8.1.3) + actioncable (= 8.1.3) + actionmailbox (= 8.1.3) + actionmailer (= 8.1.3) + actionpack (= 8.1.3) + actiontext (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activemodel (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) bundler (>= 1.15.0) - railties (= 8.0.2) - rails-dom-testing (2.2.0) + railties (= 8.1.3) + rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.2) - loofah (~> 2.21) + rails-html-sanitizer (1.7.1) + loofah (~> 2.25, >= 2.25.2) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) rails-latex (2.3.5) rails (>= 3.0.0, < 9) - rails_best_practices (1.23.2) + rails_best_practices (1.23.4) activesupport code_analyzer (~> 0.5.5) erubis i18n json + ostruct require_all (~> 3.0) ruby-progressbar - railties (8.0.2) - actionpack (= 8.0.2) - activesupport (= 8.0.2) + railties (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (13.2.1) + rake (13.4.2) rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rbs (3.9.2) + rbs (4.1.0) logger - rbtree (0.4.6) - rdoc (6.13.1) + prism (>= 1.6.0) + tsort + rbtree (0.4.7) + rdoc (7.2.0) + erb psych (>= 4.0.0) - redis (5.4.0) + tsort + redis (5.4.1) redis-client (>= 0.22.0) - redis-client (0.24.0) + redis-client (0.30.1) connection_pool - regexp_parser (2.10.0) - reline (0.6.0) + regexp_parser (2.12.0) + reline (0.6.3) io-console (~> 0.5) require_all (3.0.0) - responders (3.1.1) - actionpack (>= 5.2) - railties (>= 5.2) + responders (3.2.0) + actionpack (>= 7.0) + railties (>= 7.0) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - reverse_markdown (3.0.0) + reverse_markdown (3.0.2) nokogiri - rexml (3.4.1) - rmagick (6.1.1) + rexml (3.4.4) + rmagick (7.1.0) observer (~> 0.1) pkg-config (~> 1.4) - roo (2.10.1) + roo (3.0.0) + base64 (~> 0.2) + csv (~> 3) + logger (~> 1) nokogiri (~> 1) - rubyzip (>= 1.3.0, < 3.0.0) - roo-xls (1.2.0) + rubyzip (>= 3.0.0, < 4.0.0) + roo-xls (2.0.0) + csv nokogiri - roo (>= 2.0.0, < 3) - spreadsheet (> 0.9.0) - rouge (4.5.1) - rubocop (1.75.1) + roo (>= 2.0.0, < 4) + spreadsheet (>= 1.3.4, < 2) + rouge (5.0.0) + strscan (~> 3.1) + rubocop (1.88.2) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) - parallel (~> 1.10) + parallel (>= 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.9.3, < 3.0) - rubocop-ast (>= 1.43.0, < 2.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.43.0) + rubocop-ast (1.50.0) parser (>= 3.3.7.2) - prism (~> 1.4) - rubocop-factory_bot (2.27.1) + prism (~> 1.7) + rubocop-factory_bot (2.28.0) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) rubocop-faker (1.3.0) faker (>= 2.12.0) lint_roller (~> 1.1) rubocop (>= 1.72.1) - rubocop-minitest (0.37.1) + rubocop-minitest (0.40.0) lint_roller (~> 1.1) - rubocop (>= 1.72.1, < 2.0) + rubocop (>= 1.75.0, < 2.0) rubocop-ast (>= 1.38.0, < 2.0) - rubocop-performance (1.24.0) + rubocop-performance (1.26.1) lint_roller (~> 1.1) - rubocop (>= 1.72.1, < 2.0) - rubocop-ast (>= 1.38.0, < 2.0) - rubocop-rails (2.30.3) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) + rubocop-rails (2.36.0) activesupport (>= 4.2.0) lint_roller (~> 1.1) rack (>= 1.1) - rubocop (>= 1.72.1, < 2.0) - rubocop-ast (>= 1.38.0, < 2.0) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) ruby-filemagic (0.7.3) - ruby-lsp (0.23.13) + ruby-lsp (0.26.10) language_server-protocol (~> 3.17.0) prism (>= 1.2, < 2.0) - rbs (>= 3, < 4) - sorbet-runtime (>= 0.5.10782) + rbs (>= 3, < 5) ruby-ole (1.2.13.1) ruby-progressbar (1.13.0) ruby-rc4 (0.1.5) - ruby-saml (1.18.0) + ruby-saml (1.18.1) nokogiri (>= 1.13.10) rexml - ruby2_keywords (0.0.5) - rubyzip (2.4.1) + rubyzip (3.4.1) securerandom (0.4.1) - sentry-rails (6.5.0) + sentry-rails (6.6.2) railties (>= 5.2.0) - sentry-ruby (~> 6.5.0) - sentry-ruby (6.5.0) + sentry-ruby (~> 6.6.2) + sentry-ruby (6.6.2) bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) logger - set (1.1.1) - sexp_processor (4.17.3) + sexp_processor (4.17.5) shellwords (0.2.2) - sidekiq (7.3.9) - base64 - connection_pool (>= 2.3.0) - logger - rack (>= 2.2.4) - redis-client (>= 0.22.2) - sidekiq-cron (2.2.0) + sidekiq (8.1.6) + connection_pool (>= 3.0.0) + json (>= 2.16.0) + logger (>= 1.7.0) + rack (>= 3.2.0) + redis-client (>= 0.29.0) + sidekiq-cron (2.4.0) cronex (>= 0.13.0) fugit (~> 1.8, >= 1.11.1) globalid (>= 1.0.1) sidekiq (>= 6.5.0) - sidekiq-status (3.0.3) + sidekiq-status (4.0.0) + base64 chronic_duration - sidekiq (>= 6.0, < 8) - sidekiq-unique-jobs (8.0.10) + logger + sidekiq (>= 7, < 9) + sidekiq-unique-jobs (8.1.0) concurrent-ruby (~> 1.0, >= 1.0.5) - sidekiq (>= 7.0.0, < 8.0.0) + sidekiq (>= 7.0.0, < 9.0.0) thor (>= 1.0, < 3.0) - simplecov (0.22.0) - docile (~> 1.1) - simplecov-html (~> 0.11) - simplecov_json_formatter (~> 0.1) - simplecov-html (0.13.1) - simplecov_json_formatter (0.1.4) - snaky_hash (2.0.1) - hashie - version_gem (~> 1.1, >= 1.1.1) - solargraph (0.53.4) + simplecov (1.0.3) + snaky_hash (2.0.7) + hashie (>= 0.1.0, < 6) + version_gem (~> 1.1, >= 1.1.14) + solargraph (0.60.2) + ast (~> 2.4.3) backport (~> 1.2) - benchmark - bundler (~> 2.0) + benchmark (~> 0.4) + bundler (>= 2.0) diff-lcs (~> 1.4) - jaro_winkler (~> 1.6) + jaro_winkler (~> 1.6, >= 1.6.1) kramdown (~> 2.3) kramdown-parser-gfm (~> 1.1) logger (~> 1.6) observer (~> 0.1) + open3 (~> 0.2.1) ostruct (~> 0.6) parser (~> 3.0) - rbs (~> 3.3) - reverse_markdown (>= 2.0, < 4) - rubocop (~> 1.38) + prism (~> 1.4) + rbs (>= 3.10.0) + rdoc (~> 7.0) + reverse_markdown (~> 3.0) + rubocop (~> 1.76) + sord (~> 7.0) thor (~> 1.0) tilt (~> 2.0) yard (~> 0.9, >= 0.9.24) + yard-activesupport-concern (~> 0.0) yard-solargraph (~> 0.1) - sorbet-runtime (0.5.11966) - sorted_set (1.0.3) + sorbet-runtime (0.6.13365) + sord (7.1.0) + commander (~> 5.0) + parlour (~> 9.1) + parser + rbs (>= 3.0, < 5) + sorbet-runtime + yard + sorted_set (1.1.0) rbtree - set (~> 1.0) - spreadsheet (1.3.4) + spreadsheet (1.3.5) bigdecimal logger ruby-ole - sprockets (4.2.1) + sprockets (4.2.2) concurrent-ruby (~> 1.0) + logger rack (>= 2.2.4, < 4) sprockets-rails (3.5.2) actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - stringio (3.1.6) - sys-filesystem (1.5.5) + stringio (3.2.0) + strscan (3.1.8) + sys-filesystem (1.6.0) ffi (~> 1.1) tca_client (1.0.4) typhoeus (~> 1.0, >= 1.0.1) tcp_timeout (0.1.1) - thor (1.3.2) - tilt (2.6.0) - timeout (0.4.3) + temple (0.10.4) + thor (1.5.0) + tilt (2.8.0) + timeout (0.6.1) + tsort (0.2.0) ttfunk (1.8.0) bigdecimal (~> 3.1) - typhoeus (1.4.1) - ethon (>= 0.9.0) + typhoeus (1.6.0) + ethon (>= 0.18.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode (0.4.4.5) - unicode-display_width (3.1.4) - unicode-emoji (~> 4.0, >= 4.0.4) - unicode-emoji (4.0.4) - uri (1.0.3) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.2.0) + uri (1.1.1) useragent (0.16.11) - version_gem (1.1.6) + version_gem (1.1.14) warden (1.2.9) rack (>= 2.0.9) - webmock (3.25.1) + webmock (3.26.2) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - websocket-driver (0.7.7) + websocket-driver (0.8.2) base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - yard (0.9.37) + yard (0.9.45) + yard-activesupport-concern (0.0.1) + yard (>= 0.8) yard-solargraph (0.1.0) yard (~> 0.9) - zeitwerk (2.7.2) + zeitwerk (2.8.2) PLATFORMS aarch64-linux From 2ef8c734b836a11e76dbb7df5846eeaeef9ad39b Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 29 Jul 2026 11:08:18 +1000 Subject: [PATCH 2/3] chore: fix rubocop --- .rubocop_todo.yml | 2 +- app/api/d2l_integration_api/d2l_api.rb | 2 +- app/api/entities/user_entity.rb | 2 +- app/api/submission/generate_helpers.rb | 2 +- app/api/task_definitions_api.rb | 2 +- app/api/unit_contents_api.rb | 2 +- app/models/project.rb | 2 +- app/models/similarity/task_definition_similarity_module.rb | 4 ++-- app/models/similarity/unit_similarity_module.rb | 4 ++-- app/models/submission_history.rb | 2 +- app/models/task_definition.rb | 2 +- app/models/turn_it_in/task_definition_tii_module.rb | 4 ++-- app/sidekiq/accept_submission_job.rb | 2 +- app/sidekiq/archive_old_units_job.rb | 2 +- app/sidekiq/d2l_post_grades_job.rb | 4 ++-- lib/tasks/generate_pdfs.rake | 2 +- lib/tasks/maintenance.rake | 4 ++-- 17 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6268621a0..3e803a0cf 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -898,7 +898,7 @@ Naming/MethodParameterName: # ForbiddenPrefixes: is_, has_, have_ # AllowedMethods: is_a? # MethodDefinitionMacros: define_method, define_singleton_method -Naming/PredicateName: +Naming/PredicatePrefix: Exclude: - 'spec/**/*' - 'app/api/entities/unit_entity.rb' diff --git a/app/api/d2l_integration_api/d2l_api.rb b/app/api/d2l_integration_api/d2l_api.rb index 66f7ec635..9064d2014 100644 --- a/app/api/d2l_integration_api/d2l_api.rb +++ b/app/api/d2l_integration_api/d2l_api.rb @@ -57,7 +57,7 @@ class D2lApi < Grape::API error!({ error: 'D2L details not found' }, 404) end - d2l.destroy if d2l.present? + d2l.presence&.destroy status 204 end diff --git a/app/api/entities/user_entity.rb b/app/api/entities/user_entity.rb index 1a1155e10..3fc756c80 100644 --- a/app/api/entities/user_entity.rb +++ b/app/api/entities/user_entity.rb @@ -22,7 +22,7 @@ class UserEntity < Grape::Entity end expose :system_role, unless: :minimal do |user, options| - user.role.name if user.role.present? + user.role.presence&.name end end end diff --git a/app/api/submission/generate_helpers.rb b/app/api/submission/generate_helpers.rb index c78564e4a..88e62fa09 100644 --- a/app/api/submission/generate_helpers.rb +++ b/app/api/submission/generate_helpers.rb @@ -6,7 +6,7 @@ module Submission::GenerateHelpers # Scoops out a files array from the params provided # def scoop_files(params, upload_reqs) - files = params.reject { |key| !(key =~ /^file\d+$/) } + files = params.slice(*params.keys.grep(/\Afile\d+\z/)) error!({ error: 'Upload requirements mismatch with files provided' }, 403) if files.length != upload_reqs.length # diff --git a/app/api/task_definitions_api.rb b/app/api/task_definitions_api.rb index c50fa07b4..4f97a19b2 100644 --- a/app/api/task_definitions_api.rb +++ b/app/api/task_definitions_api.rb @@ -554,7 +554,7 @@ class TaskDefinitionsApi < Grape::API subquery = unit .tutorial_enrolments .joins(:tutorial) - .where('tutorials.tutorial_stream_id = :sid OR tutorials.tutorial_stream_id IS NULL', sid: (stream.present? ? stream.id : nil)) + .where('tutorials.tutorial_stream_id = :sid OR tutorials.tutorial_stream_id IS NULL', sid: stream.presence&.id) .select('tutorials.tutorial_stream_id as tutorial_stream_id', 'tutorials.id as tutorial_id', 'project_id').to_sql result = unit.student_tasks diff --git a/app/api/unit_contents_api.rb b/app/api/unit_contents_api.rb index 4c2432eb9..3e8feb306 100644 --- a/app/api/unit_contents_api.rb +++ b/app/api/unit_contents_api.rb @@ -151,7 +151,7 @@ def rewrite_unit_content_response( content_route = URI::DEFAULT_PARSER.unescape(params[:content_route].presence || '/') route_parts = content_route.split('/').reject(&:blank?) - error!({ error: 'Invalid unit content route' }, 422) if route_parts.any? { |part| ['.', '..'].include?(part) } + error!({ error: 'Invalid unit content route' }, 422) if route_parts.intersect?(['.', '..']) root_parts = site.root_dir.to_s.split('/').reject(&:blank?) requested_entry_path = (root_parts + route_parts).join('/') diff --git a/app/models/project.rb b/app/models/project.rb index b74cc84ad..1306f91ef 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -233,7 +233,7 @@ def tutors_and_tutorial def tutorial_enrolment_for_stream(tutorial_stream) tutorial_enrolments .joins(:tutorial) - .where('tutorials.tutorial_stream_id = :sid OR tutorials.tutorial_stream_id IS NULL', sid: (tutorial_stream.present? ? tutorial_stream.id : nil)) + .where('tutorials.tutorial_stream_id = :sid OR tutorials.tutorial_stream_id IS NULL', sid: (tutorial_stream.presence&.id)) .first end diff --git a/app/models/similarity/task_definition_similarity_module.rb b/app/models/similarity/task_definition_similarity_module.rb index d2088cf2c..722ac95d9 100644 --- a/app/models/similarity/task_definition_similarity_module.rb +++ b/app/models/similarity/task_definition_similarity_module.rb @@ -15,12 +15,12 @@ def clear_related_plagiarism logger.info "Deleting old links for task definition #{id} - #{abbreviation}" MossTaskSimilarity.joins(:task).where('tasks.task_definition_id' => id).find_each do |plnk| pair = MossTaskSimilarity.find_by(id: plnk.id) - pair.destroy! if pair.present? + pair.presence&.destroy! end JplagTaskSimilarity.joins(:task).where('tasks.task_definition_id' => id).find_each do |plnk| pair = JplagTaskSimilarity.find_by(id: plnk.id) - pair.destroy! if pair.present? + pair.presence&.destroy! end end end diff --git a/app/models/similarity/unit_similarity_module.rb b/app/models/similarity/unit_similarity_module.rb index 041040d71..f0a5050cd 100644 --- a/app/models/similarity/unit_similarity_module.rb +++ b/app/models/similarity/unit_similarity_module.rb @@ -75,7 +75,7 @@ def check_moss_similarity(force: false) # Get server to process files logger.debug 'Sending to MOSS...' - url = moss.check(to_check, ->(_) { print '.' }) + url = moss.check(to_check, ->(_) { logger.debug '.' }) logger.info "MOSS check for #{code} #{td.abbreviation} url: #{url}" @@ -182,7 +182,7 @@ def update_moss_plagiarism_stats warn_pct = td.plagiarism_warn_pct || 50 - results = moss.extract_results(url, warn_pct, ->(line) { puts line }) + results = moss.extract_results(url, warn_pct, ->(line) { logger.debug line }) # Use results results.each do |match| diff --git a/app/models/submission_history.rb b/app/models/submission_history.rb index d1f1faecc..ec9cb3789 100644 --- a/app/models/submission_history.rb +++ b/app/models/submission_history.rb @@ -111,7 +111,7 @@ def submission_zip_data buffer.string end - def has_submission_files? # rubocop:disable Naming/PredicateName + def has_submission_files? # rubocop:disable Naming/PredicatePrefix return false unless File.exist?(archive_file_name) Zip::File.open(archive_file_name) { |archive| submission_entries(archive).any? } diff --git a/app/models/task_definition.rb b/app/models/task_definition.rb index afa22855e..9980f7147 100644 --- a/app/models/task_definition.rb +++ b/app/models/task_definition.rb @@ -580,7 +580,7 @@ def to_csv_row target_day, due_week, due_day, - tutorial_stream.present? ? tutorial_stream.abbreviation : nil, + tutorial_stream.presence&.abbreviation, assess_in_portfolio_only, task_prerequisites.map do |tp| prereq = TaskDefinition.find(tp.prerequisite_id) diff --git a/app/models/turn_it_in/task_definition_tii_module.rb b/app/models/turn_it_in/task_definition_tii_module.rb index 0f7340b93..594dfa330 100644 --- a/app/models/turn_it_in/task_definition_tii_module.rb +++ b/app/models/turn_it_in/task_definition_tii_module.rb @@ -21,14 +21,14 @@ def tii_match_pct(idx) def tii_checks? TurnItIn.enabled? && !upload_requirements.empty? && - ((0..upload_requirements.length - 1).map { |i| use_tii?(i) }.inject(:|) || false) + ((0..(upload_requirements.length - 1)).map { |i| use_tii?(i) }.inject(:|) || false) end def had_tii_checks_before_last_save? TurnItIn.enabled? && upload_requirements_before_last_save.present? && !upload_requirements_before_last_save.empty? && - ((0..upload_requirements_before_last_save.length - 1).map { |i| use_tii?(i, upload_requirements_before_last_save) }.inject(:|) || false) + ((0..(upload_requirements_before_last_save.length - 1)).map { |i| use_tii?(i, upload_requirements_before_last_save) }.inject(:|) || false) end # Send all doc and docx files from the task resources to turn it in diff --git a/app/sidekiq/accept_submission_job.rb b/app/sidekiq/accept_submission_job.rb index eaaf9b380..7f03182bb 100644 --- a/app/sidekiq/accept_submission_job.rb +++ b/app/sidekiq/accept_submission_job.rb @@ -52,7 +52,7 @@ def perform(task_id, user_id, accepted_tii_eula, test_submission) ) end mail = ErrorLogMailer.error_message('Accept Submission', "Failed to convert submission to PDF for task #{task.log_details}", e) - mail.deliver if mail.present? + mail.presence&.deliver rescue StandardError => e logger.error "Failed to send error log to admin" end diff --git a/app/sidekiq/archive_old_units_job.rb b/app/sidekiq/archive_old_units_job.rb index db4ce2f11..abcc1c0ba 100644 --- a/app/sidekiq/archive_old_units_job.rb +++ b/app/sidekiq/archive_old_units_job.rb @@ -19,7 +19,7 @@ def perform # Notify system admin Sentry.capture_exception(e) if defined?(Sentry) mail = ErrorLogMailer.error_message('Archive Units', "Failed to move old units to archive", e) - mail.deliver if mail.present? + mail.presence&.deliver logger.error e rescue StandardError => e diff --git a/app/sidekiq/d2l_post_grades_job.rb b/app/sidekiq/d2l_post_grades_job.rb index 10bbf80e5..093a6dfa9 100644 --- a/app/sidekiq/d2l_post_grades_job.rb +++ b/app/sidekiq/d2l_post_grades_job.rb @@ -24,7 +24,7 @@ def perform(unit_id, user_id) logger.info "Finished posting grades for unit #{unit.id} by user #{user.id}" mail = D2lResultMailer.result_message(unit, user) - mail.deliver if mail.present? + mail.presence&.deliver logger.info "Sent email to user #{user.id} for unit #{unit.id} grade transfer result" rescue StandardError => e @@ -32,7 +32,7 @@ def perform(unit_id, user_id) begin mail = D2lResultMailer.result_message(unit, user, result_message: "failed. Please check the D2L settings for the unit, and your permissions within D2L to upload results. #{e.message}", success: false) - mail.deliver if mail.present? + mail.presence&.deliver logger.info "Sent fail email to user #{user.id} for unit #{unit.id} grade transfer result" rescue StandardError => exception diff --git a/lib/tasks/generate_pdfs.rake b/lib/tasks/generate_pdfs.rake index 5db26d07e..36b5d9d03 100644 --- a/lib/tasks/generate_pdfs.rake +++ b/lib/tasks/generate_pdfs.rake @@ -142,7 +142,7 @@ namespace :submission do # Notify system admin Sentry.capture_exception(e) if defined?(Sentry) mail = ErrorLogMailer.error_message("Failed portfolio job: #{project.log_details}", "Failed to create portfolio for project #{project.log_details}", e) - mail.deliver if mail.present? + mail.presence&.deliver rescue StandardError => e logger.error "Failed to send error log to admin" end diff --git a/lib/tasks/maintenance.rake b/lib/tasks/maintenance.rake index d7053b6e2..df4bfabc1 100644 --- a/lib/tasks/maintenance.rake +++ b/lib/tasks/maintenance.rake @@ -69,7 +69,7 @@ namespace :maintenance do begin exception = StandardError.new(message) mail = ErrorLogMailer.error_message('Accept Submission Cleanup', message, exception) - mail.deliver_now if mail.present? + mail.presence&.deliver_now rescue StandardError => e Rails.logger.error "Failed to send error log to admin for task #{task.id}!\n#{e.message}" end @@ -130,7 +130,7 @@ namespace :maintenance do OverseerAssessment .pre_queued - .includes(task: [project: :user]) + .includes(task: [{ project: :user }]) .where('created_at < ?', stale_before) .find_each do |assessment| if accept_overseer_job_present?(assessment.id) From b8f82479116d8694d327f6b00f868345b7afbc68 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:37:20 +1000 Subject: [PATCH 3/3] refactor: update methods to latest gem usage --- app/api/authentication_api.rb | 21 +++++++---------- app/api/tii/turn_it_in_hooks_api.rb | 23 +++++++++---------- app/helpers/file_helper.rb | 2 +- .../similarity/unit_similarity_module.rb | 3 ++- app/models/task.rb | 8 ++++--- app/models/unit.rb | 17 +++++++------- app/models/unit_content_site.rb | 2 +- app/sidekiq/accept_overseer_job.rb | 5 ++-- config/application.rb | 2 -- test/api/auth_test.rb | 12 +++++----- test/api/unit_contents_api_test.rb | 2 +- test/models/file_helper_test.rb | 12 +++++----- test/models/task_similarity_test.rb | 2 +- test/models/task_test.rb | 2 +- .../models/unit_content_task_resource_test.rb | 4 ++-- 15 files changed, 57 insertions(+), 60 deletions(-) diff --git a/app/api/authentication_api.rb b/app/api/authentication_api.rb index e7f446278..af0d47bab 100644 --- a/app/api/authentication_api.rb +++ b/app/api/authentication_api.rb @@ -424,19 +424,14 @@ class AuthenticationApi < Grape::API # Sign out # desc 'Sign out', - { - headers: - { - "username" => - { - description: "User username", - required: true - }, - "auth_token" => - { - description: "The user's temporary auth token", - required: true - } + headers: { + "username" => { + description: "User username", + required: true + }, + "auth_token" => { + description: "The user's temporary auth token", + required: true } } params do diff --git a/app/api/tii/turn_it_in_hooks_api.rb b/app/api/tii/turn_it_in_hooks_api.rb index 8a039bf4d..2917aa965 100644 --- a/app/api/tii/turn_it_in_hooks_api.rb +++ b/app/api/tii/turn_it_in_hooks_api.rb @@ -4,18 +4,17 @@ module Tii class TurnItInHooksApi < Grape::API include LogHelper - desc 'Accept the TurnItIn EULA', { - headers: { - "X-Turnitin-Signature" => { - description: "Valdates server identity", - required: true - }, - "X-Turnitin-EventType" => { - description: "The name of the event type for this request", - required: true - } - } - } + desc 'Accept the TurnItIn EULA', + headers: { + "X-Turnitin-Signature" => { + description: "Valdates server identity", + required: true + }, + "X-Turnitin-EventType" => { + description: "The name of the event type for this request", + required: true + } + } post 'tii_hook' do raw_data = env['api.request.input'] data = JSON.parse(raw_data) diff --git a/app/helpers/file_helper.rb b/app/helpers/file_helper.rb index 095390785..0eed071b4 100644 --- a/app/helpers/file_helper.rb +++ b/app/helpers/file_helper.rb @@ -956,7 +956,7 @@ def compress_done_files(task) input_files = Dir.entries(task_dir).select { |f| (f =~ /^\d{3}\.(cover|document|code|image)/).zero? } - Zip::File.open(zip_file, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file, create: true) do |zip| zip.mkdir task.id.to_s input_files.each do |in_file| zip.add "#{task.id}/#{in_file}", "#{task_dir}#{in_file}" diff --git a/app/models/similarity/unit_similarity_module.rb b/app/models/similarity/unit_similarity_module.rb index f0a5050cd..ad0461888 100644 --- a/app/models/similarity/unit_similarity_module.rb +++ b/app/models/similarity/unit_similarity_module.rb @@ -265,7 +265,8 @@ def run_jplag_on_done_files(task_definition, tasks_dir, tasks_with_files, report zip_file.each do |entry| dest = File.join(tasks_dir, 'base', entry.name) FileUtils.mkdir_p(File.dirname(dest)) - entry.extract(dest) { true } + dest = dest.chomp(File::SEPARATOR) + entry.extract(File.basename(dest), destination_directory: File.dirname(dest)) { true } end end end diff --git a/app/models/task.rb b/app/models/task.rb index 9a535b5a1..0830401b5 100644 --- a/app/models/task.rb +++ b/app/models/task.rb @@ -1190,11 +1190,13 @@ def extract_file_from_done(to_path, pattern, name_fn) # Extract to file/directory/symlink logger.debug "Extracting file from done: #{entry.name}" if entry.name_is_directory? - entry.extract(name_fn.call(self, to_path, entry.name)) { true } + destination = name_fn.call(self, to_path, entry.name).to_s.chomp(File::SEPARATOR) + entry.extract(File.basename(destination), destination_directory: File.dirname(destination)) { true } end end zip.glob("**/#{pattern}").each do |entry| - entry.extract(name_fn.call(self, to_path, entry.name)) { true } + destination = name_fn.call(self, to_path, entry.name) + entry.extract(File.basename(destination), destination_directory: File.dirname(destination)) { true } end end end @@ -1247,7 +1249,7 @@ def compress_new_to_done(task_dir: student_work_dir(:new, false), zip_file_path: zip_dir = File.dirname(zip_file) FileUtils.mkdir_p zip_dir - Zip::File.open(zip_file, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file, create: true) do |zip| zip.mkdir id.to_s input_files.each do |in_file| final_name = in_file diff --git a/app/models/unit.rb b/app/models/unit.rb index a3757c62e..a08528129 100644 --- a/app/models/unit.rb +++ b/app/models/unit.rb @@ -2238,7 +2238,7 @@ def get_portfolio_zip(current_user, progress_callback: nil) count = 0 # Create a new zip - Zip::File.open(portfolio_zip_name, Zip::File::CREATE) do |zip| + Zip::File.open(portfolio_zip_name, create: true) do |zip| portfolio_projects.each do |project| count += 1 progress_callback.call(message: "Compressing portfolios", rows_processed: count) if progress_callback @@ -2264,7 +2264,7 @@ def get_task_resources_zip return result if File.exist?(result) # Create a new zip - Zip::File.open(result, Zip::File::CREATE) do |zip| + Zip::File.open(result, create: true) do |zip| task_definitions.each do |td| if td.has_task_sheet? dst_path = FileHelper.sanitized_filename(td.abbreviation.to_s) + '.pdf' @@ -2308,7 +2308,7 @@ def get_task_submissions_pdf_zip(current_user, td, progress_callback: nil) count = 0 # Create a new zip - Zip::File.open(result, Zip::File::CREATE) do |zip| + Zip::File.open(result, create: true) do |zip| Dir.mktmpdir do |dir| # Extract all of the files... tasks_with_files.each do |task| @@ -2348,7 +2348,7 @@ def get_task_submissions_zip(current_user, td, progress_callback: nil) count = 0 # Create a new zip - Zip::File.open(result, Zip::File::CREATE) do |zip| + Zip::File.open(result, create: true) do |zip| Dir.mktmpdir do |dir| # Extract all of the files... tasks_with_files.each do |task| @@ -2403,7 +2403,8 @@ def import_task_files_from_zip(zip_file) task_definitions.sort_by { |td| -td.abbreviation.size }.each do |td| next unless /^#{td.abbreviation}/ =~ file_name - file.extract ("#{task_path}#{FileHelper.sanitized_filename(td.abbreviation)}#{File.extname(file.name)}") { true } + destination = "#{task_path}#{FileHelper.sanitized_filename(td.abbreviation)}#{File.extname(file.name)}" + file.extract(File.basename(destination), destination_directory: File.dirname(destination)) { true } result[:success] << { row: file.name, message: "Added as task #{td.abbreviation}" } found = true @@ -2910,7 +2911,7 @@ def generate_batch_task_zip(user, tasks) return result if File.exist?(output_zip) # Create a new zip - Zip::File.open(output_zip, Zip::File::CREATE) do |zip| + Zip::File.open(output_zip, create: true) do |zip| csv_str = mark_csv_headers # Add individual tasks... @@ -3235,7 +3236,7 @@ def upload_batch_task_zip_or_csv(user, file) tmp_file = File.join(tmp_dir, File.basename(file.name)) # get file out of zip... to tmp_file - file.extract(tmp_file) { true } + file.extract(File.basename(tmp_file), destination_directory: File.dirname(tmp_file)) { true } # copy tmp_file to dest destination_path = task.final_pdf_path(ignore_portfolio_evidence: true) @@ -3560,7 +3561,7 @@ def upload_batch_feedback_zip(user, task_definition, file, progress_callback: ni } end - Zip::File.open(repacked_zip.path, Zip::File::CREATE) do |output_zip| + Zip::File.open(repacked_zip.path, create: true) do |output_zip| output_zip.get_output_stream('marks.csv') do |f| f.write(build_batch_feedback_legacy_marks_csv(task_rows)) end diff --git a/app/models/unit_content_site.rb b/app/models/unit_content_site.rb index 3b1a02ecf..29c33af05 100644 --- a/app/models/unit_content_site.rb +++ b/app/models/unit_content_site.rb @@ -149,7 +149,7 @@ def extract_file(path) unless File.exist?(extracted_path) && File.size(extracted_path) == entry.size temporary_path = "#{extracted_path}.#{SecureRandom.hex(6)}.tmp" - entry.extract(temporary_path) { true } + entry.extract(File.basename(temporary_path), destination_directory: File.dirname(temporary_path)) { true } FileUtils.mv(temporary_path, extracted_path) end diff --git a/app/sidekiq/accept_overseer_job.rb b/app/sidekiq/accept_overseer_job.rb index 59ddd753f..7caae1f05 100644 --- a/app/sidekiq/accept_overseer_job.rb +++ b/app/sidekiq/accept_overseer_job.rb @@ -283,7 +283,7 @@ def extract_submission_entries(task, entries, work_dir, prefix) dest_path = File.join(work_dir, final_name) FileUtils.mkdir_p(File.dirname(dest_path)) - entry.extract(dest_path) { true } + entry.extract(File.basename(dest_path), destination_directory: File.dirname(dest_path)) { true } end end @@ -294,7 +294,8 @@ def extract_overseer_resource_files(assessment, work_dir) zip_file.each do |entry| dest_path = File.join(work_dir, entry.name) FileUtils.mkdir_p(File.dirname(dest_path)) - zip_file.extract(entry, dest_path) { true } # overwrite if exists + dest_path = dest_path.chomp(File::SEPARATOR) + entry.extract(File.basename(dest_path), destination_directory: File.dirname(dest_path)) { true } # overwrite if exists end end end diff --git a/config/application.rb b/config/application.rb index ee62d44ef..fcedae3f5 100644 --- a/config/application.rb +++ b/config/application.rb @@ -305,8 +305,6 @@ def self.fetch_credential_or_env(*credential_path, env_key:, default: nil) end end - config.active_support.to_time_preserves_timezone = :zone - # Generators for test framework if Rails.env.test? config.generators do |g| diff --git a/test/api/auth_test.rb b/test/api/auth_test.rb index 00aaa66c6..6fb717381 100644 --- a/test/api/auth_test.rb +++ b/test/api/auth_test.rb @@ -59,8 +59,8 @@ def test_auth_post refresh_token = User.first.auth_tokens.where(token_type: :refresh_token).last assert refresh_token.present? - assert_match(/refresh_token=#{refresh_token.authentication_token};/, last_response.cookies['refresh_token'].to_s, 'Expect refresh token to be set') - assert_match(/username=#{User.first.username};/, last_response.cookies['username'].to_s, 'Expect username to be set') + assert_equal refresh_token.authentication_token, last_response.cookies['refresh_token'].value, 'Expect refresh token to be set' + assert_equal User.first.username, last_response.cookies['username'].value, 'Expect username to be set' end def test_auth_records_sign_in_and_access_time @@ -87,8 +87,8 @@ def test_auth_no_remember assert_equal 201, last_response.status - assert_match(/refresh_token=;/, last_response.cookies['refresh_token'].to_s, 'Expect refresh token to be deleted') - assert_match(/username=;/, last_response.cookies['username'].to_s, 'Expect username to be deleted') + assert_empty last_response.cookies['refresh_token'].value, 'Expect refresh token to be deleted' + assert_empty last_response.cookies['username'].value, 'Expect username to be deleted' end # Test auth when username is invalid @@ -203,8 +203,8 @@ def test_auth_delete # 204 response code means success! assert_equal 204, last_response.status - assert_match(/username=;/, last_response.cookies['username'].to_s) - assert_match(/refresh_token=;/, last_response.cookies['refresh_token'].to_s) + assert_empty last_response.cookies['username'].value + assert_empty last_response.cookies['refresh_token'].value end def test_refresh_token diff --git a/test/api/unit_contents_api_test.rb b/test/api/unit_contents_api_test.rb index 7128ac0fe..cb185b082 100644 --- a/test/api/unit_contents_api_test.rb +++ b/test/api/unit_contents_api_test.rb @@ -49,7 +49,7 @@ def test_student_cannot_download_content_site_archive private def write_zip(path, entries) - Zip::File.open(path, Zip::File::CREATE) do |zip| + Zip::File.open(path, create: true) do |zip| entries.each do |entry_name, contents| zip.get_output_stream(entry_name) { |stream| stream.write(contents) } end diff --git a/test/models/file_helper_test.rb b/test/models/file_helper_test.rb index bfc5cb105..20b089f61 100644 --- a/test/models/file_helper_test.rb +++ b/test/models/file_helper_test.rb @@ -234,7 +234,7 @@ def test_archive_paths def test_accept_zip_upload Tempfile.create(['submission', '.zip']) do |zip_file| - Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file.path, create: true) do |zip| zip.get_output_stream('src/main.rb') { |io| io.write("puts 'hello'\n") } end @@ -253,7 +253,7 @@ def test_accept_zip_upload def test_zip_upload_rejects_unsafe_paths Tempfile.create(['submission', '.zip']) do |zip_file| - Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file.path, create: true) do |zip| zip.get_output_stream('../escape.rb') { |io| io.write("puts 'bad'\n") } end @@ -273,7 +273,7 @@ def test_zip_upload_rejects_unsafe_paths def test_zip_upload_rejects_nested_archives Tempfile.create(['submission', '.zip']) do |zip_file| - Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file.path, create: true) do |zip| zip.get_output_stream('lib/vendor.zip') { |io| io.write('nested archive') } end @@ -296,7 +296,7 @@ def test_zip_upload_accepts_entries_larger_than_file_limit Doubtfire::Application.config.max_file_size = 1_000 Tempfile.create(['submission', '.zip']) do |zip_file| - Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file.path, create: true) do |zip| zip.get_output_stream('large.txt') { |io| io.write('a' * 1_001) } end @@ -322,7 +322,7 @@ def test_zip_upload_rejects_total_uncompressed_size_over_multiplier_limit Doubtfire::Application.config.zip_uncompressed_size_multiplier = 2 Tempfile.create(['submission', '.zip']) do |zip_file| - Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file.path, create: true) do |zip| 3.times do |index| zip.get_output_stream("file-#{index}.txt") { |io| io.write('a' * 900) } end @@ -340,7 +340,7 @@ def test_zip_upload_rejects_total_uncompressed_size_over_multiplier_limit def test_zip_file_tree_lists_nested_paths Tempfile.create(['submission', '.zip']) do |zip_file| - Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip| + Zip::File.open(zip_file.path, create: true) do |zip| zip.get_output_stream('src/main.rb') { |io| io.write("puts 'hello'\n") } zip.get_output_stream('README.md') { |io| io.write("# Read me\n") } end diff --git a/test/models/task_similarity_test.rb b/test/models/task_similarity_test.rb index 2ec972a11..ce545be86 100644 --- a/test/models/task_similarity_test.rb +++ b/test/models/task_similarity_test.rb @@ -120,7 +120,7 @@ def test_jplag_similarity_pct zip_path = Rails.root.join("tmp/resources/resources.zip") FileUtils.mkdir_p(zip_path.dirname) - Zip::File.open(zip_path, Zip::File::CREATE) do |zipfile| + Zip::File.open(zip_path, create: true) do |zipfile| zipfile.add(File.basename(java_file), java_file) end diff --git a/test/models/task_test.rb b/test/models/task_test.rb index 496d3feb1..42a360627 100644 --- a/test/models/task_test.rb +++ b/test/models/task_test.rb @@ -55,7 +55,7 @@ def test_add_text_comment_with_raw_utf8_emoji_bytes convenor = unit.main_convenor_user task_definition = unit.task_definitions.first task = project.task_for_task_definition(task_definition) - comment_text = "\xF0\x9F\x98\x82".force_encoding(Encoding::UTF_8) + comment_text = "\xF0\x9F\x98\x82".b.force_encoding(Encoding::UTF_8) comment = task.add_text_comment(convenor, comment_text) diff --git a/test/models/unit_content_task_resource_test.rb b/test/models/unit_content_task_resource_test.rb index 5faca585e..59e1950bf 100644 --- a/test/models/unit_content_task_resource_test.rb +++ b/test/models/unit_content_task_resource_test.rb @@ -98,7 +98,7 @@ def with_content_site(unit, entries) def with_content_site_from_files(unit, entries) Tempfile.create(['unit-content', '.zip']) do |archive| - Zip::File.open(archive.path, Zip::File::CREATE) do |zip| + Zip::File.open(archive.path, create: true) do |zip| entries.each { |entry_name, source_path| zip.add(entry_name, source_path) } end @@ -114,7 +114,7 @@ def with_content_site_from_files(unit, entries) end def write_zip(path, entries) - Zip::File.open(path, Zip::File::CREATE) do |zip| + Zip::File.open(path, create: true) do |zip| entries.each do |entry_name, contents| zip.get_output_stream(entry_name) { |stream| stream.write(contents) } end