Upgrade to Rails 8 and Ruby 3.4.5 (#1)

* Bump Ruby to 3.4.5
* Update dependencies
* Adjust for Rails 8 and Ruby 3.5 API changes
* Mark params strings as mutable in prepapration for frozen strings in Ruby 3.5
* Update test for HTML5 sanitizer
    With Rails 7.1 the HTML5 sanitizer became the default, this breakts this test because the old sanitizer used to delete unpermitted nodes, while the new one returns their content
    The final string is safe, but different then it used to be in Rails 7.0
* Remove direct Turbo tesh helpers require & parallelize tests
* Fix Zeitwerk issues with rails extensions
* Update Resque setup for Redis 5+
* Remove unused views
* Remove GID v1 handler
This commit is contained in:
Stanko Krtalić
2025-09-02 17:02:41 +02:00
committed by GitHub
parent 657d4edcd4
commit eecdb29332
39 changed files with 508 additions and 417 deletions

View File

@@ -1 +1 @@
3.3.1
3.4.5

View File

@@ -1,17 +1,24 @@
# syntax = docker/dockerfile:1
# Make sure it matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.3.1
FROM ruby:$RUBY_VERSION-slim AS base
ARG RUBY_VERSION=3.4.5
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
# Rails app lives here
WORKDIR /rails
# Install base packages
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libsqlite3-0 libvips libjemalloc2 ffmpeg redis && \
ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so && \
rm -rf /var/lib/apt/lists /var/cache/apt/archive
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
BUNDLE_WITHOUT="development" \
LD_PRELOAD="/usr/local/lib/libjemalloc.so"
# Throw-away build stage to reduce size of final image
@@ -19,10 +26,12 @@ FROM base AS build
# Install packages need to build gems
RUN apt-get update -qq && \
apt-get install -y build-essential git pkg-config
apt-get install -y build-essential git pkg-config libyaml-dev && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Install application gems
COPY Gemfile Gemfile.lock ./
COPY Gemfile Gemfile.lock vendor ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
@@ -36,20 +45,16 @@ RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
# Final stage for app image
FROM base
# Run and own only the runtime files as a non-root user for security
RUN groupadd --system --gid 1000 rails && \
useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash
USER 1000:1000
# Configure environment defaults
ENV HTTP_IDLE_TIMEOUT=60
ENV HTTP_READ_TIMEOUT=300
ENV HTTP_WRITE_TIMEOUT=300
# Install packages needed to run the application
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y libsqlite3-0 libvips curl ffmpeg redis && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Run and own the application files as a non-root user for security
RUN useradd rails
USER rails:rails
# Copy built artifacts: gems, application
COPY --from=build --chown=rails:rails /usr/local/bundle /usr/local/bundle
COPY --from=build --chown=rails:rails /rails /rails

View File

@@ -7,14 +7,14 @@ git_source(:bc) { |repo| "https://github.com/basecamp/#{repo}" }
gem "rails", github: "rails/rails", branch: "main"
# Drivers
gem "sqlite3", "~> 1.4"
gem "redis", "~> 4.0"
gem "sqlite3", "~> 2.7"
gem "redis", "~> 5.4"
# Deployment
gem "puma", "~> 6.4"
gem "puma", "~> 6.6"
# Jobs
gem "resque", "~> 2.6.0"
gem "resque", "~> 2.7.0"
gem "resque-pool", "~> 0.7.1"
# Assets

View File

@@ -1,190 +1,204 @@
GIT
remote: https://github.com/hotwired/turbo-rails.git
revision: d7155dd51d8aeaa7128ab50a62b5cd3cb91b84f1
revision: 30cd8fcc6f82c1ad4edd1ed6069ba878f21f02b3
specs:
turbo-rails (2.0.0)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
turbo-rails (2.0.16)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
GIT
remote: https://github.com/rails/importmap-rails.git
revision: be74dead314957833f5d09e05a8daaa3526a964b
revision: 51c1a531327fc04ed4552bb0fd523eb43561b817
specs:
importmap-rails (2.0.1)
importmap-rails (2.2.2)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
GIT
remote: https://github.com/rails/propshaft.git
revision: e7cdbcd4aa9c9a390dade263bbd7c7cedc0c6442
revision: e49a9de659ff27462015e54dd832e86e762a6ddc
specs:
propshaft (0.8.0)
propshaft (1.2.1)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
GIT
remote: https://github.com/rails/rails.git
revision: 776626ff987a96201b0bdbd86d716ca6698fa8b3
revision: 02660cd9e84aa57c6cf3bf6e08cc18e18292e2fa
branch: main
specs:
actioncable (7.2.0.alpha)
actionpack (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
actioncable (8.1.0.alpha)
actionpack (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.2.0.alpha)
actionpack (= 7.2.0.alpha)
activejob (= 7.2.0.alpha)
activerecord (= 7.2.0.alpha)
activestorage (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
actionmailbox (8.1.0.alpha)
actionpack (= 8.1.0.alpha)
activejob (= 8.1.0.alpha)
activerecord (= 8.1.0.alpha)
activestorage (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
mail (>= 2.8.0)
actionmailer (7.2.0.alpha)
actionpack (= 7.2.0.alpha)
actionview (= 7.2.0.alpha)
activejob (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
actionmailer (8.1.0.alpha)
actionpack (= 8.1.0.alpha)
actionview (= 8.1.0.alpha)
activejob (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.0.alpha)
actionview (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
actionpack (8.1.0.alpha)
actionview (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (7.2.0.alpha)
actionpack (= 7.2.0.alpha)
activerecord (= 7.2.0.alpha)
activestorage (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
actiontext (8.1.0.alpha)
action_text-trix (~> 2.1.15)
actionpack (= 8.1.0.alpha)
activerecord (= 8.1.0.alpha)
activestorage (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.2.0.alpha)
activesupport (= 7.2.0.alpha)
actionview (8.1.0.alpha)
activesupport (= 8.1.0.alpha)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activejob (7.2.0.alpha)
activesupport (= 7.2.0.alpha)
activejob (8.1.0.alpha)
activesupport (= 8.1.0.alpha)
globalid (>= 0.3.6)
activemodel (7.2.0.alpha)
activesupport (= 7.2.0.alpha)
activerecord (7.2.0.alpha)
activemodel (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
activemodel (8.1.0.alpha)
activesupport (= 8.1.0.alpha)
activerecord (8.1.0.alpha)
activemodel (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
timeout (>= 0.4.0)
activestorage (7.2.0.alpha)
actionpack (= 7.2.0.alpha)
activejob (= 7.2.0.alpha)
activerecord (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
activestorage (8.1.0.alpha)
actionpack (= 8.1.0.alpha)
activejob (= 8.1.0.alpha)
activerecord (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
marcel (~> 1.0)
activesupport (7.2.0.alpha)
activesupport (8.1.0.alpha)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
rails (7.2.0.alpha)
actioncable (= 7.2.0.alpha)
actionmailbox (= 7.2.0.alpha)
actionmailer (= 7.2.0.alpha)
actionpack (= 7.2.0.alpha)
actiontext (= 7.2.0.alpha)
actionview (= 7.2.0.alpha)
activejob (= 7.2.0.alpha)
activemodel (= 7.2.0.alpha)
activerecord (= 7.2.0.alpha)
activestorage (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
uri (>= 0.13.1)
rails (8.1.0.alpha)
actioncable (= 8.1.0.alpha)
actionmailbox (= 8.1.0.alpha)
actionmailer (= 8.1.0.alpha)
actionpack (= 8.1.0.alpha)
actiontext (= 8.1.0.alpha)
actionview (= 8.1.0.alpha)
activejob (= 8.1.0.alpha)
activemodel (= 8.1.0.alpha)
activerecord (= 8.1.0.alpha)
activestorage (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
bundler (>= 1.15.0)
railties (= 7.2.0.alpha)
railties (7.2.0.alpha)
actionpack (= 7.2.0.alpha)
activesupport (= 7.2.0.alpha)
irb
railties (= 8.1.0.alpha)
railties (8.1.0.alpha)
actionpack (= 8.1.0.alpha)
activesupport (= 8.1.0.alpha)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
tsort (>= 0.2)
zeitwerk (~> 2.6)
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
base64 (0.2.0)
action_text-trix (2.1.15)
railties
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.3)
base64 (0.3.0)
bcrypt (3.1.20)
bigdecimal (3.1.6)
brakeman (6.1.1)
benchmark (0.4.1)
bigdecimal (3.2.2)
brakeman (7.1.0)
racc
builder (3.2.4)
capybara (3.39.2)
builder (3.3.0)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
chunky_png (1.4.0)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
crack (0.4.5)
concurrent-ruby (1.3.5)
connection_pool (2.5.3)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
date (3.3.4)
debug (1.9.1)
date (3.4.1)
debug (1.11.0)
irb (~> 1.10)
reline (>= 0.3.8)
drb (2.2.0)
ruby2_keywords
erubi (1.12.0)
faker (3.2.2)
drb (2.2.3)
erb (5.0.2)
erubi (1.13.1)
faker (3.5.2)
i18n (>= 1.8.11, < 2)
ffi (1.16.3)
ffi (1.17.2-aarch64-linux-gnu)
ffi (1.17.2-arm64-darwin)
ffi (1.17.2-x86_64-darwin)
ffi (1.17.2-x86_64-linux-gnu)
geared_pagination (1.2.0)
activesupport (>= 5.0)
addressable (>= 2.5.0)
globalid (1.2.1)
activesupport (>= 6.1)
hashdiff (1.1.0)
i18n (1.14.1)
hashdiff (1.2.0)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
image_processing (1.14.0)
mini_magick (>= 4.9.5, < 6)
ruby-vips (>= 2.0.17, < 3)
io-console (0.7.2)
irb (1.11.1)
rdoc
io-console (0.8.1)
irb (1.15.2)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
json (2.7.1)
jwt (2.7.1)
kredis (1.7.0)
jbuilder (2.14.1)
actionview (>= 7.0.0)
activesupport (>= 7.0.0)
json (2.13.2)
jwt (3.1.2)
base64
kredis (1.8.0)
activemodel (>= 6.0.0)
activesupport (>= 6.0.0)
redis (>= 4.2, < 6)
language_server-protocol (3.17.0.3)
loofah (2.22.0)
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
logger (1.7.0)
loofah (2.24.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -192,177 +206,198 @@ GEM
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
mini_magick (4.12.0)
marcel (1.0.4)
matrix (0.4.3)
mini_magick (5.3.1)
logger
mini_mime (1.1.5)
minitest (5.22.1)
mocha (2.1.0)
minitest (5.25.5)
mocha (2.7.1)
ruby2_keywords (>= 0.0.5)
mono_logger (1.1.2)
multi_json (1.15.0)
mustermann (3.0.0)
multi_json (1.17.0)
mustermann (3.0.4)
ruby2_keywords (~> 0.0.1)
net-http-persistent (4.0.2)
connection_pool (~> 2.2)
net-imap (0.4.9.1)
net-http-persistent (4.0.6)
connection_pool (~> 2.2, >= 2.2.4)
net-imap (0.5.9)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.4.0.1)
net-smtp (0.5.1)
net-protocol
nio4r (2.7.0)
nokogiri (1.16.2-aarch64-linux)
nio4r (2.7.4)
nokogiri (1.18.9-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.16.2-arm64-darwin)
nokogiri (1.18.9-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-darwin)
nokogiri (1.18.9-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.16.2-x86_64-linux)
nokogiri (1.18.9-x86_64-linux-gnu)
racc (~> 1.4)
openssl (3.2.0)
parallel (1.24.0)
parser (3.3.0.3)
openssl (3.3.0)
parallel (1.27.0)
parser (3.3.9.0)
ast (~> 2.4.1)
racc
platform_agent (1.0.1)
activesupport (>= 5.2.0)
useragent (~> 0.16.3)
psych (5.1.2)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
prism (1.4.0)
psych (5.2.6)
date
stringio
public_suffix (5.0.4)
puma (6.4.2)
public_suffix (6.0.2)
puma (6.6.1)
nio4r (~> 2.0)
racc (1.7.3)
rack (2.2.8)
rack-protection (3.2.0)
racc (1.8.1)
rack (3.2.0)
rack-protection (4.1.1)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-session (1.0.2)
rack (< 3)
rack-test (2.1.0)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-session (2.1.1)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (1.0.0)
rack (< 3)
webrick
rails-dom-testing (2.2.0)
rackup (2.2.1)
rack (>= 3)
rails-dom-testing (2.3.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (~> 1.14)
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_autolink (1.1.8)
actionview (> 3.1)
activesupport (> 3.1)
railties (> 3.1)
rainbow (3.1.1)
rake (13.1.0)
rdoc (6.6.2)
rake (13.3.0)
rdoc (6.14.2)
erb
psych (>= 4.0.0)
redis (4.8.1)
redis (5.4.1)
redis-client (>= 0.22.0)
redis-client (0.25.2)
connection_pool
redis-namespace (1.11.0)
redis (>= 4)
regexp_parser (2.9.0)
reline (0.4.2)
regexp_parser (2.11.2)
reline (0.6.2)
io-console (~> 0.5)
resque (2.6.0)
mono_logger (~> 1.0)
resque (2.7.0)
mono_logger (~> 1)
multi_json (~> 1.0)
redis-namespace (~> 1.6)
sinatra (>= 0.9.2)
resque-pool (0.7.1)
rake (>= 10.0, < 14.0)
resque (>= 1.22, < 3)
rexml (3.2.6)
rqrcode (2.2.0)
rexml (3.4.1)
rqrcode (3.1.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
rubocop (1.59.0)
rqrcode_core (~> 2.0)
rqrcode_core (2.0.0)
rubocop (1.80.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.2.2.4)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.30.0, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.46.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-minitest (0.34.4)
rubocop (>= 1.39, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rails (2.23.1)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.46.0)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-performance (1.25.0)
lint_roller (~> 1.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.33.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rails-omakase (1.0.0)
rubocop
rubocop-minitest
rubocop-performance
rubocop-rails
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0)
rubocop-rails-omakase (1.1.0)
rubocop (>= 1.72)
rubocop-performance (>= 1.24)
rubocop-rails (>= 2.30)
ruby-progressbar (1.13.0)
ruby-vips (2.2.0)
ruby-vips (2.2.5)
ffi (~> 1.12)
logger
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
selenium-webdriver (4.16.0)
rubyzip (3.0.2)
securerandom (0.4.1)
selenium-webdriver (4.35.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
rubyzip (>= 1.2.2, < 4.0)
websocket (~> 1.0)
sentry-rails (5.16.1)
sentry-rails (5.26.0)
railties (>= 5.0)
sentry-ruby (~> 5.16.1)
sentry-ruby (5.16.1)
sentry-ruby (~> 5.26.0)
sentry-ruby (5.26.0)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
sinatra (3.2.0)
sinatra (4.1.1)
logger (>= 1.6.0)
mustermann (~> 3.0)
rack (~> 2.2, >= 2.2.4)
rack-protection (= 3.2.0)
rack (>= 3.0.0, < 4)
rack-protection (= 4.1.1)
rack-session (>= 2.0.0, < 3)
tilt (~> 2.0)
sqlite3 (1.7.0-aarch64-linux)
sqlite3 (1.7.0-arm64-darwin)
sqlite3 (1.7.0-x86_64-darwin)
sqlite3 (1.7.0-x86_64-linux)
stimulus-rails (1.3.3)
sqlite3 (2.7.3-aarch64-linux-gnu)
sqlite3 (2.7.3-arm64-darwin)
sqlite3 (2.7.3-x86_64-darwin)
sqlite3 (2.7.3-x86_64-linux-gnu)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.0)
thor (1.3.0)
thruster (0.1.7-aarch64-linux)
thruster (0.1.7-arm64-darwin)
thruster (0.1.7-x86_64-darwin)
thruster (0.1.7-x86_64-linux)
tilt (2.3.0)
timeout (0.4.1)
stringio (3.1.7)
thor (1.4.0)
thruster (0.1.15-aarch64-linux)
thruster (0.1.15-arm64-darwin)
thruster (0.1.15-x86_64-darwin)
thruster (0.1.15-x86_64-linux)
tilt (2.6.1)
timeout (0.4.3)
tsort (0.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.5.0)
useragent (0.16.10)
web-push (3.0.1)
jwt (~> 2.0)
unicode-display_width (3.1.5)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
useragent (0.16.11)
web-push (3.0.2)
jwt (~> 3.0)
openssl (~> 3.0)
webmock (3.19.1)
webmock (3.25.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.8.1)
websocket (1.2.10)
websocket-driver (0.7.6)
websocket (1.2.11)
websocket-driver (0.8.0)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.13)
zeitwerk (2.7.3)
PLATFORMS
aarch64-linux
@@ -385,18 +420,18 @@ DEPENDENCIES
net-http-persistent
platform_agent
propshaft!
puma (~> 6.4)
puma (~> 6.6)
rails!
rails_autolink
redis (~> 4.0)
resque (~> 2.6.0)
redis (~> 5.4)
resque (~> 2.7.0)
resque-pool (~> 0.7.1)
rqrcode
rubocop-rails-omakase
selenium-webdriver
sentry-rails
sentry-ruby
sqlite3 (~> 1.4)
sqlite3 (~> 2.7)
stimulus-rails
thruster
turbo-rails!

View File

@@ -1,4 +1,7 @@
class Rooms::ClosedsController < RoomsController
before_action :set_room, only: %i[ show edit update ]
before_action :ensure_can_administer, only: %i[ update ]
before_action :remember_last_room_visited, only: :show
before_action :force_room_type, only: %i[ edit update ]
DEFAULT_ROOM_NAME = "New room"

View File

@@ -1,6 +1,8 @@
class Rooms::InvolvementsController < ApplicationController
include RoomScoped
before_action :ensure_can_administer, only: %i[ update ]
def show
@involvement = @membership.involvement
end

View File

@@ -1,4 +1,7 @@
class Rooms::OpensController < RoomsController
before_action :set_room, only: %i[ show edit update ]
before_action :ensure_can_administer, only: %i[ update ]
before_action :remember_last_room_visited, only: :show
before_action :force_room_type, only: %i[ edit update ]
DEFAULT_ROOM_NAME = "New room"

View File

@@ -1,6 +1,6 @@
class RoomsController < ApplicationController
before_action :set_room, only: %i[ edit update show destroy ]
before_action :ensure_can_administer, only: %i[ update destroy ]
before_action :set_room, only: %i[ show destroy ]
before_action :ensure_can_administer, only: %i[ destroy ]
before_action :remember_last_room_visited, only: :show
def index

View File

@@ -6,7 +6,7 @@ class Membership < ApplicationRecord
after_destroy_commit { user.reset_remote_connections }
enum involvement: %w[ invisible nothing mentions everything ].index_by(&:itself), _prefix: :involved_in
enum :involvement, %w[ invisible nothing mentions everything ].index_by(&:itself), prefix: :involved_in
scope :with_ordered_room, -> { includes(:room).joins(:room).order("LOWER(rooms.name)") }
scope :without_direct_rooms, -> { joins(:room).where.not(room: { type: "Rooms::Direct" }) }

View File

@@ -53,12 +53,12 @@ class Opengraph::Fetch
# the body of any large responses. But that header could be wrong or
# missing. To be on the safe side, we'll read the body in chunks, and bail
# if it runs over our size limit.
"".tap do |body|
StringIO.new.tap do |body|
response.read_body do |chunk|
return nil if body.bytesize + chunk.bytesize > MAX_BODY_SIZE
return nil if body.string.bytesize + chunk.bytesize > MAX_BODY_SIZE
body << chunk
end
end
end.string
end
def response_valid?(response)

View File

@@ -2,7 +2,7 @@ module User::Role
extend ActiveSupport::Concern
included do
enum role: %i[ member administrator bot ]
enum :role, %i[ member administrator bot ]
end
def can_administer?(record = nil)

View File

@@ -53,7 +53,7 @@ class Webhook < ApplicationRecord
end
def extract_text_from(response)
response.body.force_encoding("UTF-8") if response.code == "200" && response.content_type.in?(%w[ text/html text/plain ])
response.body.dup.force_encoding("UTF-8") if response.code == "200" && response.content_type.in?(%w[ text/html text/plain ])
end
def receive_text_reply_to(room, text:)

View File

@@ -1,27 +1,7 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'brakeman' is installed as part of a gem, and
# this file is here to facilitate running it.
#
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
bundle_binstub = File.expand_path("bundle", __dir__)
if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end
require "rubygems"
require "bundler/setup"
ARGV.unshift("--ensure-latest")
load Gem.bin_path("brakeman", "brakeman")

6
bin/bundler-audit Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
require_relative "../config/boot"
require "bundler/audit/cli"
ARGV.concat %w[ --config config/bundler-audit.yml ] if ARGV.empty? || ARGV.include?("check")
Bundler::Audit::CLI.start

6
bin/ci Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
require_relative "../config/boot"
require "active_support/continuous_integration"
CI = ActiveSupport::ContinuousIntegration
require_relative "../config/ci.rb"

2
bin/dev Executable file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env ruby
exec "./bin/rails", "server", *ARGV

View File

@@ -1,27 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'rubocop' is installed as part of a gem, and
# this file is here to facilitate running it.
#
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
bundle_binstub = File.expand_path("bundle", __dir__)
if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end
require "rubygems"
require "bundler/setup"
# Explicit RuboCop config increases performance slightly while avoiding config confusion.
ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__))
load Gem.bin_path("rubocop", "rubocop")

View File

@@ -1,45 +1,32 @@
#!/bin/bash
set -eo pipefail
#!/usr/bin/env ruby
require "fileutils"
app_root="$( cd "$(dirname "$0")/.."; pwd )"
app_name=campfire
APP_ROOT = File.expand_path("..", __dir__)
# Use application binstubs
export PATH="$app_root/bin:$PATH"
def system!(*args)
system(*args, exception: true)
end
announce() {
echo
echo "--- $@"
}
if [ "$RAILS_ENV" == "production" ]
then
echo "RAILS_ENV is production; bailing out"
if ENV["RAILS_ENV"] == "production"
puts "RAILS_ENV is production; bailing out"
exit
fi
end
announce "Installing dependencies"
mise install
bundle install
FileUtils.chdir APP_ROOT do
puts "== Installing dependencies =="
system "mise install"
system("bundle check") || system!("bundle install")
announce "Preparing database"
if [[ $* == *--reset* ]]; then
rm -rf ./storage/{db,files}
rails db:migrate:reset
else
rails db:prepare
fi
puts "\n== Preparing database =="
if ARGV.include?("--reset")
system "rm -rf ./storage/{db,files}"
system! "bin/rails db:reset"
end
system! "bin/rails db:prepare"
announce "Cleaning up old logs, caches, and temporary files"
rails log:clear tmp:clear
puts "\n== Removing old logs and tempfiles =="
system! "bin/rails log:clear tmp:clear"
announce "Restarting services"
rails restart
if [ -d "$HOME/.puma-dev" ]; then
announce "Configuring puma-dev"
ln -nfs "$app_root" "$HOME/.puma-dev/$app_name"
announce "Checking that https://$app_name.test/up is live: "
curl -Is "https://$app_name.test/up" | head -n 1
fi
puts "\n== Restarting services =="
system! "bin/rails restart"
end

5
bin/thrust Executable file
View File

@@ -0,0 +1,5 @@
#!/usr/bin/env ruby
require "rubygems"
require "bundler/setup"
load Gem.bin_path("thruster", "thrust")

View File

@@ -7,7 +7,12 @@ Bundler.require(*Rails.groups)
module Campfire
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.0
config.load_defaults 8.1
# Please, add to the `ignore` list any other `lib` subdirectories that do
# not contain `.rb` files, or that should not be reloaded or eager loaded.
# Common ones are `templates`, `generators`, or `middleware`, for example.
config.autoload_lib(ignore: %w[assets tasks rails_ext])
# Fallback to English if translation key is missing
config.i18n.fallbacks = true

View File

@@ -3,13 +3,13 @@
{
"warning_type": "Dynamic Render Path",
"warning_code": 15,
"fingerprint": "3ba57fe811dd7154100cbd8ca7a262c5a316d50d0d44b877fec8dbfdf710cdd0",
"fingerprint": "58c19ad06ce51511be9d6d9e5828f4a0ed96ab52c963ff37b4b4a606620ab66b",
"check_name": "Render",
"message": "Render path contains parameter value",
"file": "app/views/messages/show.html.erb",
"line": 1,
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
"code": "render(action => @room.messages.find(params[:id]), {})",
"code": "render(action => @room.messages.find(params[:id]), { :locals => ({ :brakemanunresolvedmodel => @room.messages.find(params[:id]) }) })",
"render_path": [
{
"type": "controller",
@@ -33,31 +33,7 @@
22
],
"note": ""
},
{
"warning_type": "File Access",
"warning_code": 16,
"fingerprint": "64b6a0c35632fbde1eaa8c5441b070fec379a983ac91997b5b48177d6d36b024",
"check_name": "SendFile",
"message": "Model attribute used in file name",
"file": "app/controllers/users/avatars_controller.rb",
"line": 14,
"link": "https://brakemanscanner.org/docs/warning_types/file_access/",
"code": "send_file(ActiveStorage::Blob.service.path_for(User.find(params[:user_id]).avatar.variant(:resize_to_limit => ([512, 512]), :format => :webp).processed.key), :content_type => \"image/webp\", :disposition => :inline)",
"render_path": null,
"location": {
"type": "method",
"class": "Users::AvatarsController",
"method": "show"
},
"user_input": "User.find(params[:user_id]).avatar",
"confidence": "Weak",
"cwe_id": [
22
],
"note": ""
}
],
"updated": "2024-01-18 16:36:00 -0800",
"brakeman_version": "6.1.1"
"brakeman_version": "7.1.0"
}

5
config/bundler-audit.yml Normal file
View File

@@ -0,0 +1,5 @@
# Audit all gems listed in the Gemfile for known security problems by running bin/bundler-audit.
# CVEs that are not relevant to the application can be enumerated on the ignore list below.
ignore:
- CVE-THAT-DOES-NOT-APPLY

21
config/ci.rb Normal file
View File

@@ -0,0 +1,21 @@
# Run using bin/ci
CI.run do
step "Setup", "bin/setup --skip-server"
step "Style: Ruby", "bin/rubocop"
step "Security: Gem audit", "bin/bundler-audit"
step "Security: Importmap vulnerability audit", "bin/importmap audit"
step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error"
step "Tests: Rails", "bin/rails test"
step "Tests: System", "bin/rails test:system"
step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant"
if success?
step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff"
else
failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again."
end
end

View File

@@ -7,7 +7,7 @@
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 10 } %>
retries: 100
timeout: 5000
default_transaction_mode: immediate
development:

View File

@@ -3,10 +3,8 @@ require "active_support/core_ext/integer/time"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded any time
# it changes. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Make code changes take effect immediately without server restart.
config.enable_reloading = true
# Do not eager load code on boot.
config.eager_load = false
@@ -14,18 +12,18 @@ Rails.application.configure do
# Show full error reports.
config.consider_all_requests_local = true
# Enable server timing
# Enable server timing.
config.server_timing = true
# Enable/disable caching. By default caching is disabled.
# Run rails dev:cache to toggle caching.
# Enable/disable Action Controller caching. By default Action Controller caching is disabled.
# Run rails dev:cache to toggle Action Controller caching.
if Rails.root.join("tmp/caching-dev.txt").exist?
config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
config.cache_store = :redis_cache_store
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{2.days.to_i}"
"cache-control" => "public, max-age=#{2.days.to_i}"
}
else
config.action_controller.perform_caching = false
@@ -51,6 +49,9 @@ Rails.application.configure do
# Highlight code that triggered database queries in logs.
config.active_record.verbose_query_logs = true
# Append comments with runtime information tags to SQL queries in logs.
config.active_record.query_log_tags_enabled = true
# Allow the app to be served from any host.
config.hosts = []
@@ -66,6 +67,18 @@ Rails.application.configure do
# Uncomment to test with production class job queue
# config.active_job.queue_adapter = :resque
# Highlight code that enqueued background job in logs.
config.active_job.verbose_enqueue_logs = true
# Suppress logger output for asset requests.
config.assets.quiet = true
# Annotate rendered view with file names.
config.action_view.annotate_rendered_view_with_filenames = true
# Raise error when a before_action's only/except options reference missing actions.
config.action_controller.raise_on_missing_callback_actions = true
# Visit /rails/locks to see the locks
config.middleware.insert_before Rack::Sendfile, ActionDispatch::DebugLocks
end

View File

@@ -5,18 +5,30 @@ Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
config.enable_reloading = false
# 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 on boot for better performance and memory savings (ignored by Rake tasks).
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Cache digest stamped assets for far-future expiry.
# Short cache for others: robots.txt, sitemap.xml, 404.html, etc.
config.public_file_server.headers = {
"cache-control" => lambda do |path, _|
if path.start_with?("/assets/")
# Files in /assets/ are expected to be fully immutable.
# If the content change the URL too.
"public, immutable, max-age=#{1.year.to_i}"
else
# For anything else we cache for 1 minute.
"public, max-age=#{1.minute.to_i}, stale-while-revalidate=#{5.minutes.to_i}"
end
end
}
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
# or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
# config.require_master_key = true
@@ -27,9 +39,15 @@ Rails.application.configure do
# Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
# config.assume_ssl = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# Skip http-to-https redirect for the default health check endpoint.
# config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }
# Log to STDOUT by default
config.logger = ActiveSupport::Logger.new(STDOUT)
.tap { |logger| logger.formatter = ::Logger::Formatter.new }
@@ -43,6 +61,12 @@ Rails.application.configure do
# for everything.
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
# Prevent health checks from clogging up the logs.
config.silence_healthcheck_path = "/up"
# Don't log any deprecations.
config.active_support.report_deprecations = false
# Cache in memory for now
config.cache_store = :redis_cache_store
@@ -65,8 +89,8 @@ Rails.application.configure do
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
# SQLite is good, actually
config.active_record.sqlite3_production_warning = false
# Only use :id for inspections in production.
config.active_record.attributes_for_inspect = [ :id ]
config.active_job.queue_adapter = :resque
end

View File

@@ -8,18 +8,19 @@ require "active_support/core_ext/integer/time"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Turn false under Spring and add config.action_view.cache_template_loading = true.
config.cache_classes = true
# While tests run files are not watched, reloading is not necessary.
config.enable_reloading = false
# Eager loading loads your whole application. When running a single test locally,
# this probably isn't necessary. It's a good idea to do in a continuous integration
# system, or in some way before deploying your code.
# Eager loading loads your entire application. When running a single test locally,
# this is usually not necessary, and can slow down your test suite. However, it's
# recommended that you enable it in continuous integration systems to ensure eager
# loading is working properly before deploying your code.
config.eager_load = ENV["CI"].present?
# Configure public file server for tests with Cache-Control for performance.
config.public_file_server.enabled = true
config.public_file_server.headers = {
"Cache-Control" => "public, max-age=#{1.hour.to_i}"
"cache-control" => "public, max-age=#{1.hour.to_i}"
}
# Show full error reports and disable caching.
@@ -45,6 +46,9 @@ Rails.application.configure do
# Tell Active Support which deprecation messages to disallow.
config.active_support.disallowed_deprecation_warnings = []
# Raise error when a before_action's only/except options reference missing actions.
config.action_controller.raise_on_missing_callback_actions = true
# Raises error for missing translations.
# config.i18n.raise_on_missing_translations = true

View File

@@ -4,5 +4,5 @@
# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported
# notations and behaviors.
Rails.application.config.filter_parameters += [
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :endpoint, "message.body"
:passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc, :endpoint, "message.body"
]

View File

@@ -11,6 +11,6 @@
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym "RESTful"
# end
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym "HTTP"
end

View File

@@ -1,36 +0,0 @@
module SQLite3Configuration
private
def configure_connection
super
if @config[:retries]
retries = self.class.type_cast_config_to_integer(@config[:retries])
raw_connection.busy_handler do |count|
(count <= retries).tap { |result| sleep count * 0.001 if result }
end
end
end
end
module SQLite3DumpConfiguration
def structure_dump(filename, extra_flags)
args = []
args.concat(Array(extra_flags)) if extra_flags
args << db_config.database
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
if ignore_tables.any?
ignore_tables = connection.data_sources.select { |table| ignore_tables.any? { |pattern| pattern === table } }
condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
args << "SELECT sql || ';' FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
else
args << ".schema --nosys"
end
run_cmd("sqlite3", args, filename)
end
end
ActiveSupport.on_load :active_record do
ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend SQLite3Configuration
ActiveRecord::Tasks::SQLiteDatabaseTasks.prepend SQLite3DumpConfiguration
end

View File

@@ -0,0 +1,22 @@
# This migration comes from active_storage (originally 20190112182829)
class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
def up
return unless table_exists?(:active_storage_blobs)
unless column_exists?(:active_storage_blobs, :service_name)
add_column :active_storage_blobs, :service_name, :string
if configured_service = ActiveStorage::Blob.service.name
ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
end
change_column :active_storage_blobs, :service_name, :string, null: false
end
end
def down
return unless table_exists?(:active_storage_blobs)
remove_column :active_storage_blobs, :service_name
end
end

View File

@@ -0,0 +1,27 @@
# This migration comes from active_storage (originally 20191206030411)
class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
def change
return unless table_exists?(:active_storage_blobs)
# Use Active Record's configured type for primary key
create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t|
t.belongs_to :blob, null: false, index: false, type: blobs_primary_key_type
t.string :variation_digest, null: false
t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true
t.foreign_key :active_storage_blobs, column: :blob_id
end
end
private
def primary_key_type
config = Rails.configuration.generators
config.options[config.orm][:primary_key_type] || :primary_key
end
def blobs_primary_key_type
pkey_name = connection.primary_key(:active_storage_blobs)
pkey_column = connection.columns(:active_storage_blobs).find { |c| c.name == pkey_name }
pkey_column.bigint? ? :bigint : pkey_column.type
end
end

View File

@@ -0,0 +1,8 @@
# This migration comes from active_storage (originally 20211119233751)
class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0]
def change
return unless table_exists?(:active_storage_blobs)
change_column_null(:active_storage_blobs, :checksum, true)
end
end

View File

@@ -6,8 +6,6 @@ FOREIGN KEY ("user_id")
);
CREATE INDEX "index_push_subscriptions_on_user_id" ON "push_subscriptions" ("user_id");
CREATE INDEX "idx_on_endpoint_p256dh_key_auth_key_7553014576" ON "push_subscriptions" ("endpoint", "p256dh_key", "auth_key");
CREATE TABLE IF NOT EXISTS "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar, "created_at" datetime(6) NOT NULL);
CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key");
CREATE TABLE IF NOT EXISTS "active_storage_attachments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" bigint NOT NULL, "blob_id" bigint NOT NULL, "created_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_c3b3935057"
FOREIGN KEY ("blob_id")
REFERENCES "active_storage_blobs" ("id")
@@ -69,7 +67,12 @@ CREATE INDEX "index_webhooks_on_user_id" ON "webhooks" ("user_id");
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "role" integer DEFAULT 0 NOT NULL, "email_address" varchar DEFAULT NULL, "password_digest" varchar DEFAULT NULL, "active" boolean DEFAULT 1, "bio" text DEFAULT NULL, "bot_token" varchar DEFAULT NULL);
CREATE UNIQUE INDEX "index_users_on_email_address" ON "users" ("email_address");
CREATE UNIQUE INDEX "index_users_on_bot_token" ON "users" ("bot_token");
CREATE TABLE IF NOT EXISTS "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar, "created_at" datetime(6) NOT NULL);
CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") /*application='Campfire'*/;
INSERT INTO "schema_migrations" (version) VALUES
('20250825100959'),
('20250825100958'),
('20250825100957'),
('20240209110503'),
('20240131105830'),
('20240130213001'),

View File

@@ -13,7 +13,13 @@ ActiveSupport.on_load(:action_text_content) do
def attachable_from_possibly_expired_sgid(sgid)
if message = sgid&.split("--")&.first
encoded_message = JSON.parse Base64.strict_decode64(message)
decoded_gid = Marshal.load Base64.urlsafe_decode64(encoded_message.dig("_rails", "message"))
decoded_gid = if data = encoded_message.dig("_rails", "data")
data
else
nil
end
model = GlobalID.find(decoded_gid)
model.model_name.to_s.in?(ATTACHABLES_PERMITTED_WITH_INVALID_SIGNATURES) ? model : nil

View File

@@ -7,6 +7,6 @@ task "resque:pool:setup" do
Resque::Pool.after_prefork do |job|
ActiveRecord::Base.establish_connection
Resque.redis.client.reconnect
Resque.redis.client.close
end
end

View File

@@ -7,14 +7,14 @@ class Messages::ByBotsControlleTest < ActionDispatch::IntegrationTest
test "create" do
assert_difference -> { Message.count }, +1 do
post room_bot_messages_url(@room, users(:bender).bot_key), params: "Hello Bot World!"
post room_bot_messages_url(@room, users(:bender).bot_key), params: +"Hello Bot World!"
assert_equal "Hello Bot World!", Message.last.plain_text_body
end
end
test "create with UTF-8 content" do
assert_difference -> { Message.count }, +1 do
post room_bot_messages_url(@room, users(:bender).bot_key), params: "Hello 👋!"
post room_bot_messages_url(@room, users(:bender).bot_key), params: +"Hello 👋!"
assert_equal "Hello 👋!", Message.last.plain_text_body
end
end
@@ -36,7 +36,7 @@ class Messages::ByBotsControlleTest < ActionDispatch::IntegrationTest
test "create does not trigger a webhook to the sending bot in a direct room" do
assert_no_enqueued_jobs only: Bot::WebhookJob do
post room_bot_messages_url(rooms(:bender_and_kevin), users(:bender).bot_key), params: "Talking to myself again!"
post room_bot_messages_url(rooms(:bender_and_kevin), users(:bender).bot_key), params: +"Talking to myself again!"
end
end

View File

@@ -122,8 +122,8 @@ class Opengraph::MetadataTest < ActiveSupport::TestCase
metadata = Opengraph::Metadata.from_url("https://www.example.com")
assert metadata.valid?
assert_equal "Hey!", metadata.title
assert_equal "Hello", metadata.description
assert_equal "Hey!alert('hi')", metadata.title
assert_equal "Helloalert('hi')", metadata.description
end
test "remove encoded tags from title and description" do

View File

@@ -9,11 +9,9 @@ require "webmock/minitest"
WebMock.enable!
class ActiveSupport::TestCase
# FIXME: Why isn't this included in ActiveSupport::TestCase by default?
include ActiveJob::TestHelper, Turbo::Broadcastable::TestHelper
include ActiveJob::TestHelper
# FIXME: sqlite3 isn't correctly creating the additional databases per core
# parallelize(workers: :number_of_processors)
parallelize(workers: :number_of_processors)
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all