diff --git a/.env.development b/.env.development index 9f636c9c..441ada83 100644 --- a/.env.development +++ b/.env.development @@ -7,5 +7,5 @@ DB_USER=postgres DB_PASS=postgres DB_NAME=pub-relay -DOMAIN=example.com +DOMAIN=www.example.com HTTPS=true diff --git a/.env.test b/.env.test index 33f0880e..ca007f63 100644 --- a/.env.test +++ b/.env.test @@ -7,5 +7,5 @@ DB_USER=postgres DB_PASS=postgres DB_NAME=pub-relay -DOMAIN=example.com +DOMAIN=www.example.com diff --git a/Gemfile b/Gemfile index 128080e0..1606a9bc 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '3.3.6' -gem 'rails', '~> 7' +gem 'rails', '~> 7.2', '>= 7.2.2.1' gem 'sprockets', '~> 4.2.1' gem 'pg', '>= 0.18', '< 2.0' gem 'puma', '~> 6.4' diff --git a/Gemfile.lock b/Gemfile.lock index 53246c37..84bc8a4c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,92 +1,90 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.1.3.2) - actionpack (= 7.1.3.2) - activesupport (= 7.1.3.2) + actioncable (7.2.2.1) + actionpack (= 7.2.2.1) + activesupport (= 7.2.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.3.2) - actionpack (= 7.1.3.2) - activejob (= 7.1.3.2) - activerecord (= 7.1.3.2) - activestorage (= 7.1.3.2) - activesupport (= 7.1.3.2) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.1.3.2) - actionpack (= 7.1.3.2) - actionview (= 7.1.3.2) - activejob (= 7.1.3.2) - activesupport (= 7.1.3.2) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp + actionmailbox (7.2.2.1) + actionpack (= 7.2.2.1) + activejob (= 7.2.2.1) + activerecord (= 7.2.2.1) + activestorage (= 7.2.2.1) + activesupport (= 7.2.2.1) + mail (>= 2.8.0) + actionmailer (7.2.2.1) + actionpack (= 7.2.2.1) + actionview (= 7.2.2.1) + activejob (= 7.2.2.1) + activesupport (= 7.2.2.1) + mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.1.3.2) - actionview (= 7.1.3.2) - activesupport (= 7.1.3.2) + actionpack (7.2.2.1) + actionview (= 7.2.2.1) + activesupport (= 7.2.2.1) nokogiri (>= 1.8.5) racc - rack (>= 2.2.4) + rack (>= 2.2.4, < 3.2) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.3.2) - actionpack (= 7.1.3.2) - activerecord (= 7.1.3.2) - activestorage (= 7.1.3.2) - activesupport (= 7.1.3.2) + useragent (~> 0.16) + actiontext (7.2.2.1) + actionpack (= 7.2.2.1) + activerecord (= 7.2.2.1) + activestorage (= 7.2.2.1) + activesupport (= 7.2.2.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.3.2) - activesupport (= 7.1.3.2) + actionview (7.2.2.1) + activesupport (= 7.2.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.1.3.2) - activesupport (= 7.1.3.2) + activejob (7.2.2.1) + activesupport (= 7.2.2.1) globalid (>= 0.3.6) - activemodel (7.1.3.2) - activesupport (= 7.1.3.2) - activerecord (7.1.3.2) - activemodel (= 7.1.3.2) - activesupport (= 7.1.3.2) + activemodel (7.2.2.1) + activesupport (= 7.2.2.1) + activerecord (7.2.2.1) + activemodel (= 7.2.2.1) + activesupport (= 7.2.2.1) timeout (>= 0.4.0) - activestorage (7.1.3.2) - actionpack (= 7.1.3.2) - activejob (= 7.1.3.2) - activerecord (= 7.1.3.2) - activesupport (= 7.1.3.2) + activestorage (7.2.2.1) + actionpack (= 7.2.2.1) + activejob (= 7.2.2.1) + activerecord (= 7.2.2.1) + activesupport (= 7.2.2.1) marcel (~> 1.0) - activesupport (7.1.3.2) + activesupport (7.2.2.1) 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) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) base64 (0.2.0) + benchmark (0.4.0) bigdecimal (3.1.6) bootsnap (1.18.3) msgpack (~> 1.2) builder (3.2.4) byebug (11.1.3) - concurrent-ruby (1.2.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) crass (1.0.6) - date (3.3.4) + date (3.4.1) diff-lcs (1.5.0) domain_name (0.6.20240107) dotenv (3.1.0) @@ -117,8 +115,8 @@ GEM i18n (1.14.1) concurrent-ruby (~> 1.0) io-console (0.7.2) - irb (1.11.2) - rdoc + irb (1.14.2) + rdoc (>= 4.0.0) reline (>= 0.4.2) listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) @@ -126,6 +124,7 @@ GEM llhttp-ffi (0.5.0) ffi-compiler (~> 1.0) rake (~> 13.0) + logger (1.6.3) lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) @@ -139,20 +138,19 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) + marcel (1.0.4) mini_mime (1.1.5) mini_portile2 (2.8.6) minitest (5.22.2) msgpack (1.7.2) - mutex_m (0.2.0) - net-imap (0.4.10) + net-imap (0.5.1) 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.0) net-protocol nio4r (2.7.0) nokogiri (1.16.4) @@ -175,20 +173,20 @@ GEM rackup (1.0.0) rack (< 3) webrick - rails (7.1.3.2) - actioncable (= 7.1.3.2) - actionmailbox (= 7.1.3.2) - actionmailer (= 7.1.3.2) - actionpack (= 7.1.3.2) - actiontext (= 7.1.3.2) - actionview (= 7.1.3.2) - activejob (= 7.1.3.2) - activemodel (= 7.1.3.2) - activerecord (= 7.1.3.2) - activestorage (= 7.1.3.2) - activesupport (= 7.1.3.2) + rails (7.2.2.1) + actioncable (= 7.2.2.1) + actionmailbox (= 7.2.2.1) + actionmailer (= 7.2.2.1) + actionpack (= 7.2.2.1) + actiontext (= 7.2.2.1) + actionview (= 7.2.2.1) + activejob (= 7.2.2.1) + activemodel (= 7.2.2.1) + activerecord (= 7.2.2.1) + activestorage (= 7.2.2.1) + activesupport (= 7.2.2.1) bundler (>= 1.15.0) - railties (= 7.1.3.2) + railties (= 7.2.2.1) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -196,10 +194,10 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.1.3.2) - actionpack (= 7.1.3.2) - activesupport (= 7.1.3.2) - irb + railties (7.2.2.1) + actionpack (= 7.2.2.1) + activesupport (= 7.2.2.1) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) @@ -261,6 +259,7 @@ GEM rspec-support (3.12.2) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) + securerandom (0.4.0) sidekiq (7.2.2) concurrent-ruby (< 2) connection_pool (>= 2.3.0) @@ -277,11 +276,12 @@ GEM rack (>= 2.2.4, < 4) stringio (3.1.0) thor (1.3.0) - timeout (0.4.1) + timeout (0.4.2) tzinfo (2.0.6) concurrent-ruby (~> 1.0) tzinfo-data (1.2024.1) tzinfo (>= 1.0.0) + useragent (0.16.11) webrick (1.8.2) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) @@ -306,7 +306,7 @@ DEPENDENCIES oj pg (>= 0.18, < 2.0) puma (~> 6.4) - rails (~> 7) + rails (~> 7.2, >= 7.2.2.1) redis (~> 5.1) redis-namespace (~> 1.10) redis-rails diff --git a/app/controllers/actors_controller.rb b/app/controllers/actors_controller.rb index bb485a47..57e536f8 100644 --- a/app/controllers/actors_controller.rb +++ b/app/controllers/actors_controller.rb @@ -16,4 +16,14 @@ def show }, }) end + + private + + def actor_url + "https://#{ENV['DOMAIN']}/actor" + end + + def inbox_url + "https://#{ENV['DOMAIN']}/inbox" + end end diff --git a/app/controllers/webfinger_controller.rb b/app/controllers/webfinger_controller.rb index bdd89d08..9a50e390 100644 --- a/app/controllers/webfinger_controller.rb +++ b/app/controllers/webfinger_controller.rb @@ -10,7 +10,7 @@ def show links: [{ rel: 'self', type: 'application/activity+json', - href: actor_url, + href: "https://#{ENV['DOMAIN']}/actor", }], }) end @@ -18,6 +18,6 @@ def show private def acct - 'acct:relay@' + Rails.application.default_url_options[:host] + "acct:relay@#{ENV["DOMAIN"]}" end end diff --git a/app/workers/deliver_worker.rb b/app/workers/deliver_worker.rb index ca976258..5f24aef9 100644 --- a/app/workers/deliver_worker.rb +++ b/app/workers/deliver_worker.rb @@ -34,7 +34,7 @@ def perform(url, body) private def actor_url - PubRelay::Application.routes.url_helpers.actor_url + "https://#{ENV['DOMAIN']}/actor" end def http_client diff --git a/app/workers/process_worker.rb b/app/workers/process_worker.rb index 2eba90c2..0c0f6c8e 100644 --- a/app/workers/process_worker.rb +++ b/app/workers/process_worker.rb @@ -62,14 +62,14 @@ def subscribe! accept_activity = Oj.dump({ '@context': %w(https://www.w3.org/ns/activitystreams https://w3id.org/security/v1), - id: URI.join(Rails.application.routes.url_helpers.root_url, "/actor#accepts/follows/#{domain}"), + id: "https://#{ENV["DOMAIN"]}/actor#accepts/follows/#{domain}", type: 'Accept', - actor: URI.join(Rails.application.routes.url_helpers.root_url, "/actor"), + actor: "https://#{ENV["DOMAIN"]}/actor", object: { id: @json['id'], type: "Follow", actor: @actor['id'], - object: URI.join(Rails.application.routes.url_helpers.root_url, "/actor") + object: "https://#{ENV["DOMAIN"]}/actor" }, }) diff --git a/bin/rails b/bin/rails index 5badb2fd..efc03774 100755 --- a/bin/rails +++ b/bin/rails @@ -1,9 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/bin/rake b/bin/rake index d87d5f57..4fbf10b9 100755 --- a/bin/rake +++ b/bin/rake @@ -1,9 +1,4 @@ #!/usr/bin/env ruby -begin - load File.expand_path('../spring', __FILE__) -rescue LoadError => e - raise unless e.message.include?('spring') -end -require_relative '../config/boot' -require 'rake' +require_relative "../config/boot" +require "rake" Rake.application.run diff --git a/bin/relayctl b/bin/relayctl index a629bcb9..086763da 100755 --- a/bin/relayctl +++ b/bin/relayctl @@ -1,5 +1,5 @@ #!/usr/bin/env ruby require_relative '../config/boot' require_relative '../config/environment' -require_relative '../lib/cli' -PubRelay::CLI.start(ARGV) +require_relative '../lib/pub_relay/cli' +PubRelay::Cli.start(ARGV) diff --git a/bin/setup b/bin/setup index a334d86a..0472aca4 100755 --- a/bin/setup +++ b/bin/setup @@ -1,33 +1,37 @@ #!/usr/bin/env ruby -require 'fileutils' -include FileUtils +require "fileutils" -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) +APP_ROOT = File.expand_path("..", __dir__) +APP_NAME = "pub-relay" def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") + system(*args, exception: true) end -chdir APP_ROOT do - # This script is a starting point to setup your application. +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. # Add necessary setup steps to this file. - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") # puts "\n== Copying sample files ==" - # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" # end puts "\n== Preparing database ==" - system! 'bin/rails db:setup' + system! "bin/rails db:prepare" puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' + system! "bin/rails log:clear tmp:clear" puts "\n== Restarting application server ==" - system! 'bin/rails restart' + system! "bin/rails restart" + + # puts "\n== Configuring puma-dev ==" + # system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}" + # system "curl -Is https://#{APP_NAME}.test/up | head -n 1" end diff --git a/config/application.rb b/config/application.rb index ec6c2978..dce0ed57 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,4 +1,4 @@ -require_relative 'boot' +require_relative "boot" require "rails" # Pick the frameworks you want: @@ -8,9 +8,10 @@ require "active_storage/engine" require "action_controller/railtie" require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" require "action_view/railtie" require "action_cable/engine" -# require "sprockets/railtie" require "rails/test_unit/railtie" # Require the gems listed in Gemfile, including any gems @@ -24,21 +25,24 @@ module PubRelay class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 7.1 + config.load_defaults 7.2 - # Settings in config/environments/* take precedence over those specified here. - # Application configuration can go into files in config/initializers - # -- all .rb files in that directory are automatically loaded after loading - # the framework and any gems in your application. + # 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]) + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") # Only loads a smaller set of middleware suitable for API only apps. # Middleware like session, flash, cookies can be added back manually. # Skip views, helpers and assets when generating a new resource. config.api_only = true - - Rails.application.default_url_options[:host] = ENV.fetch('DOMAIN') { "localhost:#{ENV.fetch('PORT', 3000)}" } - Rails.application.default_url_options[:protocol] = ENV['HTTPS'] == 'true' ? 'https' : 'http' - - config.cache_store = :redis_store, { url: ENV['REDIS_URL'] } end end diff --git a/config/boot.rb b/config/boot.rb index b9e460ce..988a5ddc 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,4 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) -require 'bundler/setup' # Set up gems listed in the Gemfile. -require 'bootsnap/setup' # Speed up boot time by caching expensive operations. +require "bundler/setup" # Set up gems listed in the Gemfile. +require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/config/environment.rb b/config/environment.rb index 426333bb..cac53157 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ # Load the Rails application. -require_relative 'application' +require_relative "application" # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 34211cc5..5b3302e5 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,13 +1,12 @@ +require "active_support/core_ext/integer/time" + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # see https://weseek.co.jp/tech/680/ - config.hosts << "your-domain-here.example.com" - - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development + # 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 + config.enable_reloading = true # Do not eager load code on boot. config.eager_load = false @@ -15,14 +14,17 @@ # Show full error reports. config.consider_all_requests_local = true + # Enable server timing. + config.server_timing = true + # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. - if Rails.root.join('tmp', 'caching-dev.txt').exist? + if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.cache_store = :memory_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 @@ -30,30 +32,47 @@ config.cache_store = :null_store end - # Store uploaded files on the local file system (see config/storage.yml for options) + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false + config.action_mailer.default_url_options = { host: "localhost", port: 3000 } + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load # Highlight code that triggered database queries in logs. config.active_record.verbose_query_logs = true + # Highlight code that enqueued background job in logs. + config.active_job.verbose_enqueue_logs = true + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + config.action_view.annotate_rendered_view_with_filenames = true - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true - # Use an evented file watcher to asynchronously detect changes in source code, - # routes, locales, etc. This feature depends on the listen gem. - config.file_watcher = ActiveSupport::EventedFileUpdateChecker + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true config.hosts << ENV['DOMAIN'] config.force_ssl = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 52e87255..f0313263 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,8 +1,10 @@ +require "active_support/core_ext/integer/time" + 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 @@ -11,15 +13,15 @@ config.eager_load = true # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false + config.consider_all_requests_local = false config.action_controller.perform_caching = true - # 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). + # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment + # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). # config.require_master_key = true - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. + # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. + # config.public_file_server.enabled = false config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? ActiveSupport::Logger.new(STDOUT).tap do |logger| @@ -28,37 +30,52 @@ end # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' + # config.asset_host = "http://assets.example.com" # Specifies the header that your server uses for sending files. - # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX - # Store uploaded files on the local file system (see config/storage.yml for options) + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local - # Mount Action Cable outside main process or domain + # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil - # config.action_cable.url = 'wss://example.com/cable' - # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + # config.action_cable.url = "wss://example.com/cable" + # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true + config.force_ssl = true - # Use the lowest log level to ensure availability of diagnostic information - # when problems arise. - config.log_level = :info + # 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 } + .then { |logger| ActiveSupport::TaggedLogging.new(logger) } # Prepend all log lines with the following tags. config.log_tags = [ :request_id ] + # "info" includes generic and useful information about system operation, but avoids logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). If you + # want to log everything, set the level to "debug". + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") + # Use a different cache store in production. - # config.cache_store = :mem_cache_store + config.cache_store = :redis_store, { url: ENV['REDIS_URL'] } - # Use a real queuing backend for Active Job (and separate queues per environment) - # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "pub-relay_#{Rails.env}" + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "pub_relay_production" + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. @@ -69,20 +86,20 @@ # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true - # Send deprecation notices to registered listeners. - config.active_support.deprecation = :notify - - # Use default logging formatter so that PID and timestamp are not suppressed. - config.log_formatter = ::Logger::Formatter.new - - # Use a different logger for distributed setups. - # require 'syslog/logger' - # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - - config.lograge.enabled = true + # Don't log any deprecations. + config.active_support.report_deprecations = false # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - config.active_record.cache_versioning = false + # Only use :id for inspections in production. + config.active_record.attributes_for_inspect = [ :id ] + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } end diff --git a/config/environments/test.rb b/config/environments/test.rb index 0ec9e7a3..0d11bfee 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,36 +1,44 @@ +require "active_support/core_ext/integer/time" + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = false + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false - # Do not eager load code on boot. This avoids loading your whole application - # just for the purpose of running a single test. If you are using a tool that - # preloads Rails for running tests, you may have to set it to true. - config.eager_load = false + # 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. - config.consider_all_requests_local = true + config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + # Render exception templates for rescuable exceptions and raise for other exceptions. + config.action_dispatch.show_exceptions = :rescuable # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false - # Store uploaded files on the local file system in a temporary directory + # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test + # Disable caching for Action Mailer templates even if Action Controller + # caching is enabled. config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -38,11 +46,25 @@ # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test + # Unlike controllers, the mailer instance doesn't have any context about the + # incoming request so you'll need to provide the :host parameter yourself. + config.action_mailer.default_url_options = { host: "www.example.com" } + # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true - config.active_record.cache_versioning = false + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true end diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb index 3b1c1b5e..0c5dd99a 100644 --- a/config/initializers/cors.rb +++ b/config/initializers/cors.rb @@ -1,15 +1,15 @@ # Be sure to restart your server when you modify this file. # Avoid CORS issues when API is called from the frontend app. -# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. +# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin Ajax requests. # Read more: https://github.com/cyu/rack-cors # Rails.application.config.middleware.insert_before 0, Rack::Cors do # allow do -# origins 'example.com' +# origins "example.com" # -# resource '*', +# resource "*", # headers: :any, # methods: [:get, :post, :put, :patch, :delete, :options, :head] # end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4a994e1e..c010b83d 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,4 +1,8 @@ # Be sure to restart your server when you modify this file. -# Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf9..3860f659 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -4,13 +4,13 @@ # are locale specific, and you may define rules for as many different # locales as you wish. All of these examples are active by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" # inflect.uncountable %w( fish sheep ) # end # These inflection rules are supported but not enabled by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' +# inflect.acronym "RESTful" # end diff --git a/config/puma.rb b/config/puma.rb index a5eccf81..9b1fa201 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,34 +1,36 @@ -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. -# -threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -threads threads_count, threads_count +# This configuration file will be evaluated by Puma. The top-level methods that +# are invoked here are part of Puma's configuration DSL. For more information +# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. -# Specifies the `port` that Puma will listen on to receive requests; default is 3000. -# -port ENV.fetch("PORT") { 3000 } - -# Specifies the `environment` that Puma will run in. -# environment ENV.fetch("RAILS_ENV") { "development" } -# Specifies the number of `workers` to boot in clustered mode. -# Workers are forked webserver processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. # -# workers ENV.fetch("WEB_CONCURRENCY") { 2 } - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. +# The ideal number of threads per worker depends both on how much time the +# application spends waiting for IO operations and on how much you wish to +# to prioritize throughput over latency. # -# preload_app! +# As a rule of thumb, increasing the number of threads will increase how much +# traffic a given process can handle (throughput), but due to CRuby's +# Global VM Lock (GVL) it has diminishing returns and will degrade the +# response time (latency) of the application. +# +# The default is set to 3 threads as it's deemed a decent compromise between +# throughput and latency for the average Rails application. +# +# Any libraries that use a connection pool or another resource pool should +# be configured to provide at least as many connections as the number of +# threads. This includes Active Record's `pool` parameter in `database.yml`. +threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) +threads threads_count, threads_count -# Allow puma to be restarted by `rails restart` command. +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +port ENV.fetch("PORT", 3000) + +# Allow puma to be restarted by `bin/rails restart` command. plugin :tmp_restart + +# Specify the PID file. Defaults to tmp/pids/server.pid in development. +# In other environments, only set the PID file if requested. +pidfile ENV["PIDFILE"] if ENV["PIDFILE"] diff --git a/db/schema.rb b/db/schema.rb index be888999..1680ad01 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -2,16 +2,15 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_07_11_165942) do - +ActiveRecord::Schema[7.2].define(version: 2024_12_13_134746) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -25,5 +24,4 @@ t.string "inbox_url", default: "", null: false t.index ["domain"], name: "index_subscriptions_on_domain", unique: true end - end diff --git a/lib/cli.rb b/lib/pub_relay/cli.rb similarity index 96% rename from lib/cli.rb rename to lib/pub_relay/cli.rb index b14e4db5..2628a7be 100644 --- a/lib/cli.rb +++ b/lib/pub_relay/cli.rb @@ -1,7 +1,7 @@ require 'thor' module PubRelay - class CLI < Thor + class Cli < Thor desc 'list', 'List all subscribed servers' def list ::Subscription.pluck(:domain).each do |domain| diff --git a/spec/requests/actors_spec.rb b/spec/requests/actors_spec.rb index 74612be5..f1027240 100644 --- a/spec/requests/actors_spec.rb +++ b/spec/requests/actors_spec.rb @@ -5,8 +5,8 @@ let(:public_key_pem) { Actor.key.public_key.to_pem } before do - allow(ENV).to receive(:fetch).and_call_original - allow(ENV).to receive(:fetch).with("LOCAL_DOMAIN", "www.example.com").and_return("www.example.com") + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with("DOMAIN").and_return("www.example.com") get '/actor' end @@ -25,13 +25,13 @@ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1" ], - "id" =>"http://www.example.com/actor", + "id" =>"https://www.example.com/actor", "type" => "Service", "preferredUsername" => "relay", - "inbox" => "http://www.example.com/inbox", + "inbox" => "https://www.example.com/inbox", "publicKey" => { - "id" => "http://www.example.com/actor#main-key", - "owner"=>"http://www.example.com/actor", + "id" => "https://www.example.com/actor#main-key", + "owner"=>"https://www.example.com/actor", "publicKeyPem" => public_key_pem } } diff --git a/spec/requests/webfinger_spec.rb b/spec/requests/webfinger_spec.rb index 37a28086..71921aa0 100644 --- a/spec/requests/webfinger_spec.rb +++ b/spec/requests/webfinger_spec.rb @@ -10,16 +10,26 @@ end context "when params[:resource] is wrong" do + before do + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with("DOMAIN").and_return("www.example.com") + end + it "should return 404" do - get '/.well-known/webfinger?resource=acct:wrong@example.com' + get '/.well-known/webfinger?resource=acct:wrong@www.example.com' expect(response).to have_http_status 404 end end context "when params[:resource] is present" do + before do + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with("DOMAIN").and_return("www.example.com") + end + it 'should return 200' do - get '/.well-known/webfinger?resource=acct:relay@example.com' + get '/.well-known/webfinger?resource=acct:relay@www.example.com' expect(response).to have_http_status 200 end