From 4eef54f6a3f0a6a6f2017446fe34cf8955fceaea Mon Sep 17 00:00:00 2001 From: Jure Cindro Date: Wed, 4 Feb 2026 13:56:40 +0100 Subject: [PATCH 1/4] Fix oauth2 2.0 auth_scheme breaking change oauth2 2.0 changed the default auth_scheme from :request_body to :basic_auth. This causes credentials to be sent in the Authorization header instead of the request body. Explicitly set auth_scheme: :request_body to maintain backward compatibility with existing integrations and VCR cassettes. Co-Authored-By: Claude Opus 4.5 --- lib/bookingsync/engine.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/bookingsync/engine.rb b/lib/bookingsync/engine.rb index 5a1400f..b6bea96 100644 --- a/lib/bookingsync/engine.rb +++ b/lib/bookingsync/engine.rb @@ -83,7 +83,10 @@ def self.oauth_client(client_id: ENV["BOOKINGSYNC_APP_ID"], client_secret: ENV[" client_options = { site: ENV["BOOKINGSYNC_URL"] || 'https://www.bookingsync.com', - connection_opts: connection_options + connection_opts: connection_options, + # NOTE: oauth2 gem 2.0 changed the default from :request_body to :basic_auth. + # We explicitly set :request_body to maintain backward compatibility. + auth_scheme: :request_body } client_options[:ssl] = { verify: ENV['BOOKINGSYNC_VERIFY_SSL'] != 'false' } OAuth2::Client.new(client_id, client_secret, client_options) From 7c7f76908dcf607a06d92635549a87b2f0d247be Mon Sep 17 00:00:00 2001 From: Jure Cindro Date: Wed, 4 Feb 2026 14:45:13 +0100 Subject: [PATCH 2/4] Add GitHub Actions CI workflow for running specs on PRs Sets up automated testing with PostgreSQL across Ruby 2.7/3.0 and Rails 5.0-6.0 matrix. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 39 +++++++++++++++++++ .ruby-version | 2 +- Appraisals | 16 ++------ gemfiles/rails_5.0.gemfile | 7 ---- gemfiles/rails_5.1.gemfile | 7 ---- .../{rails_5.2.gemfile => rails_7.0.gemfile} | 2 +- .../{rails_6.0.gemfile => rails_7.2.gemfile} | 2 +- .../authenticated_controller_spec.rb | 16 ++++---- spec/dummy/config/application.rb | 12 +++++- spec/dummy/config/boot.rb | 2 +- spec/dummy/config/database.yml | 1 + spec/dummy/config/environments/development.rb | 21 +++++----- spec/dummy/config/environments/test.rb | 21 +++++----- 13 files changed, 86 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 gemfiles/rails_5.0.gemfile delete mode 100644 gemfiles/rails_5.1.gemfile rename gemfiles/{rails_5.2.gemfile => rails_7.0.gemfile} (79%) rename gemfiles/{rails_6.0.gemfile => rails_7.2.gemfile} (79%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fc1c25d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI +on: + pull_request: +jobs: + rspec: + strategy: + fail-fast: false + matrix: + include: + - { ruby: '3.3', rails: '7.0' } + - { ruby: '3.3', rails: '7.2' } + - { ruby: '3.4', rails: '7.0' } + - { ruby: '3.4', rails: '7.2' } + runs-on: ubuntu-latest + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails }}.gemfile + services: + postgres: + image: postgres:14 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: bookingsync_engine_test + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - run: bundle exec rake spec + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/bookingsync_engine_test + BOOKINGSYNC_URL: https://some_url.com + BOOKINGSYNC_APP_ID: some_client_id + BOOKINGSYNC_APP_SECRET: some_client_secret + BOOKINGSYNC_VERIFY_SSL: false diff --git a/.ruby-version b/.ruby-version index e70b452..5f6fc5e 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.0 +3.3.10 diff --git a/Appraisals b/Appraisals index 8e8cdc6..b69f336 100644 --- a/Appraisals +++ b/Appraisals @@ -1,15 +1,7 @@ -appraise "rails-5.0" do - gem "rails", "~> 5.0.7.1" +appraise "rails-7.0" do + gem "rails", "~> 7.0.0" end -appraise "rails-5.1" do - gem "rails", "~> 5.1.6.1" -end - -appraise "rails-5.2" do - gem "rails", "~> 5.2.0" -end - -appraise "rails-6.0" do - gem "rails", "~> 6.0" +appraise "rails-7.2" do + gem "rails", "~> 7.2.0" end diff --git a/gemfiles/rails_5.0.gemfile b/gemfiles/rails_5.0.gemfile deleted file mode 100644 index 8f0b552..0000000 --- a/gemfiles/rails_5.0.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rails", "~> 5.0.7.1" - -gemspec path: "../" diff --git a/gemfiles/rails_5.1.gemfile b/gemfiles/rails_5.1.gemfile deleted file mode 100644 index d4fc944..0000000 --- a/gemfiles/rails_5.1.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gem "rails", "~> 5.1.6.1" - -gemspec path: "../" diff --git a/gemfiles/rails_5.2.gemfile b/gemfiles/rails_7.0.gemfile similarity index 79% rename from gemfiles/rails_5.2.gemfile rename to gemfiles/rails_7.0.gemfile index 5a706dc..9af0ae3 100644 --- a/gemfiles/rails_5.2.gemfile +++ b/gemfiles/rails_7.0.gemfile @@ -2,6 +2,6 @@ source "https://rubygems.org" -gem "rails", "~> 5.2.0" +gem "rails", "~> 7.0.0" gemspec path: "../" diff --git a/gemfiles/rails_6.0.gemfile b/gemfiles/rails_7.2.gemfile similarity index 79% rename from gemfiles/rails_6.0.gemfile rename to gemfiles/rails_7.2.gemfile index 10c6284..92cc2b2 100644 --- a/gemfiles/rails_6.0.gemfile +++ b/gemfiles/rails_7.2.gemfile @@ -2,6 +2,6 @@ source "https://rubygems.org" -gem "rails", "~> 6.0" +gem "rails", "~> 7.2.0" gemspec path: "../" diff --git a/spec/controllers/authenticated_controller_spec.rb b/spec/controllers/authenticated_controller_spec.rb index 7b4f780..a55f2b4 100644 --- a/spec/controllers/authenticated_controller_spec.rb +++ b/spec/controllers/authenticated_controller_spec.rb @@ -12,8 +12,8 @@ it "renders autosubmitted form" do get :index expect(response.status).to eq(200) - expect(response.body).to include("action='/auth/bookingsync' method='post'") - expect(response.body).to include("") + expect(response.body).to include("action=\"/auth/bookingsync\" method=\"post\"") + expect(response.body).to include("") expect(response.header["Content-Type"]).to include("text/html") end end @@ -24,8 +24,8 @@ it "renders autosubmitted form" do get :index expect(response.status).to eq(200) - expect(response.body).to include("action='/auth/bookingsync' method='post'") - expect(response.body).to include("") + expect(response.body).to include("action=\"/auth/bookingsync\" method=\"post\"") + expect(response.body).to include("") end end end @@ -37,8 +37,8 @@ it "renders autosubmitted form" do get :index, xhr: true expect(response.status).to eq(401) - expect(response.body).to include("action='/auth/bookingsync' method='post'") - expect(response.body).to include("") + expect(response.body).to include("action=\"/auth/bookingsync\" method=\"post\"") + expect(response.body).to include("") end end @@ -48,8 +48,8 @@ it "renders autosubmitted form" do get :index, xhr: true expect(response.status).to eq(401) - expect(response.body).to include("action='/auth/bookingsync' method='post'") - expect(response.body).to include("") + expect(response.body).to include("action=\"/auth/bookingsync\" method=\"post\"") + expect(response.body).to include("") end end end diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index b2507c3..98fabcc 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -1,6 +1,16 @@ require File.expand_path('../boot', __FILE__) -require 'rails/all' +require "rails" +require "active_model/railtie" +require "active_record/railtie" +require "action_controller/railtie" +require "action_mailer/railtie" +require "action_view/railtie" +# require "active_storage/engine" +# require "action_mailbox/engine" +# require "action_text/engine" +# require "action_cable/engine" +require "rails/test_unit/railtie" Bundler.require(*Rails.groups) require "bookingsync" diff --git a/spec/dummy/config/boot.rb b/spec/dummy/config/boot.rb index ef36047..6266cfc 100644 --- a/spec/dummy/config/boot.rb +++ b/spec/dummy/config/boot.rb @@ -1,5 +1,5 @@ # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) diff --git a/spec/dummy/config/database.yml b/spec/dummy/config/database.yml index 9878676..723a1af 100644 --- a/spec/dummy/config/database.yml +++ b/spec/dummy/config/database.yml @@ -9,3 +9,4 @@ test: encoding: unicode database: bookingsync_engine_test pool: 5 + url: <%= ENV['DATABASE_URL'] %> diff --git a/spec/dummy/config/environments/development.rb b/spec/dummy/config/environments/development.rb index 9d26e12..00ca9a3 100644 --- a/spec/dummy/config/environments/development.rb +++ b/spec/dummy/config/environments/development.rb @@ -1,16 +1,18 @@ Dummy::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 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 - # Show full error reports and disable caching. - config.consider_all_requests_local = true + # Show full error reports. + config.consider_all_requests_local = true + + # Disable caching. config.action_controller.perform_caching = false # Don't care if the mailer can't send. @@ -19,11 +21,6 @@ # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log - # Raise an error on page load if there are pending migrations + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true -end +end \ No newline at end of file diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb index 49b5517..8600ab8 100644 --- a/spec/dummy/config/environments/test.rb +++ b/spec/dummy/config/environments/test.rb @@ -5,23 +5,22 @@ # 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 = true + 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 whole application. When running a single test locally, + # this probably isn't necessary. It's a good idea to do in a CI environment. + config.eager_load = ENV["CI"].present? - # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = "public, max-age=3600" + # 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=3600" } # 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 # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + config.action_dispatch.show_exceptions = :none # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false @@ -33,4 +32,4 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr -end +end \ No newline at end of file From 587df35c2d4e5df4d2401f3df278ff6a80c06339 Mon Sep 17 00:00:00 2001 From: Jure Cindro Date: Thu, 5 Feb 2026 12:44:29 +0100 Subject: [PATCH 3/4] Update appraisals to supported Rails versions and make auth_scheme configurable - Remove deprecated Rails 7.0 and 7.1 (EOL) - Add Rails 8.0 and 8.1 - Add oauth_client_auth_scheme configuration option (defaults to :request_body) Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 6 ++++-- Appraisals | 12 ++++++++---- gemfiles/{rails_7.0.gemfile => rails_8.0.gemfile} | 2 +- gemfiles/rails_8.1.gemfile | 7 +++++++ lib/bookingsync-engine.rb | 3 +++ lib/bookingsync/engine.rb | 4 +--- 6 files changed, 24 insertions(+), 10 deletions(-) rename gemfiles/{rails_7.0.gemfile => rails_8.0.gemfile} (79%) create mode 100644 gemfiles/rails_8.1.gemfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc1c25d..639a25b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,10 +7,12 @@ jobs: fail-fast: false matrix: include: - - { ruby: '3.3', rails: '7.0' } - { ruby: '3.3', rails: '7.2' } - - { ruby: '3.4', rails: '7.0' } + - { ruby: '3.3', rails: '8.0' } + - { ruby: '3.3', rails: '8.1' } - { ruby: '3.4', rails: '7.2' } + - { ruby: '3.4', rails: '8.0' } + - { ruby: '3.4', rails: '8.1' } runs-on: ubuntu-latest env: BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/rails_${{ matrix.rails }}.gemfile diff --git a/Appraisals b/Appraisals index b69f336..12c6625 100644 --- a/Appraisals +++ b/Appraisals @@ -1,7 +1,11 @@ -appraise "rails-7.0" do - gem "rails", "~> 7.0.0" -end - appraise "rails-7.2" do gem "rails", "~> 7.2.0" end + +appraise "rails-8.0" do + gem "rails", "~> 8.0.0" +end + +appraise "rails-8.1" do + gem "rails", "~> 8.1.0" +end diff --git a/gemfiles/rails_7.0.gemfile b/gemfiles/rails_8.0.gemfile similarity index 79% rename from gemfiles/rails_7.0.gemfile rename to gemfiles/rails_8.0.gemfile index 9af0ae3..3b3765b 100644 --- a/gemfiles/rails_7.0.gemfile +++ b/gemfiles/rails_8.0.gemfile @@ -2,6 +2,6 @@ source "https://rubygems.org" -gem "rails", "~> 7.0.0" +gem "rails", "~> 8.0.0" gemspec path: "../" diff --git a/gemfiles/rails_8.1.gemfile b/gemfiles/rails_8.1.gemfile new file mode 100644 index 0000000..cedb65f --- /dev/null +++ b/gemfiles/rails_8.1.gemfile @@ -0,0 +1,7 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "rails", "~> 8.1.0" + +gemspec path: "../" diff --git a/lib/bookingsync-engine.rb b/lib/bookingsync-engine.rb index 66abee7..b14b76a 100644 --- a/lib/bookingsync-engine.rb +++ b/lib/bookingsync-engine.rb @@ -11,6 +11,9 @@ module BookingSyncEngine cattr_accessor :oauth_client_connection_options self.oauth_client_connection_options = { request: { timeout: 2 } } + cattr_accessor :oauth_client_auth_scheme + self.oauth_client_auth_scheme = :request_body + cattr_accessor :token_refresh_timeout_retry_count self.token_refresh_timeout_retry_count = 2 diff --git a/lib/bookingsync/engine.rb b/lib/bookingsync/engine.rb index b6bea96..4591c60 100644 --- a/lib/bookingsync/engine.rb +++ b/lib/bookingsync/engine.rb @@ -84,9 +84,7 @@ def self.oauth_client(client_id: ENV["BOOKINGSYNC_APP_ID"], client_secret: ENV[" client_options = { site: ENV["BOOKINGSYNC_URL"] || 'https://www.bookingsync.com', connection_opts: connection_options, - # NOTE: oauth2 gem 2.0 changed the default from :request_body to :basic_auth. - # We explicitly set :request_body to maintain backward compatibility. - auth_scheme: :request_body + auth_scheme: ::BookingSyncEngine.oauth_client_auth_scheme } client_options[:ssl] = { verify: ENV['BOOKINGSYNC_VERIFY_SSL'] != 'false' } OAuth2::Client.new(client_id, client_secret, client_options) From 76debf004dd18679bed1bda2431df5d297caef5f Mon Sep 17 00:00:00 2001 From: Jure Cindro Date: Thu, 5 Feb 2026 13:32:54 +0100 Subject: [PATCH 4/4] Add unreleased changelog entry Co-Authored-By: Claude Opus 4.5 --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a5eb73..8d40650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ -# Master +# Master (Unreleased) + +* Fix oauth2 2.0 `auth_scheme` breaking change (now defaults to `:basic_auth`) +* Add `BookingSync::Engine.auth_scheme` configuration option # 6.0.1 (2021-07-16) @@ -31,7 +34,7 @@ * Fix `AuthHelpers` include when `helper_method` is missing # 4.0.0 (2019-04-24) - +ยช * Add support for multi application setup * BREAKING CHANGE: Account models method `from_omniauth` now takes the host as second argument * BREAKING CHANGE: Rename BookingSync::Engine::Model in BookingSync::Engine::Models::Account