Skip to content

Commit ebfee15

Browse files
authoredSep 18, 2024··
Merge pull request #17 from os0x/rails71
Support Rails 7.1
2 parents 019668b + 7bcbe52 commit ebfee15

9 files changed

+83
-100
lines changed
 

‎.github/workflows/ci.yml

+5-23
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,20 @@ jobs:
1111
fail-fast: false
1212
matrix:
1313
ruby:
14-
- '2.6'
1514
- '2.7'
1615
- '3.0'
1716
- '3.1'
17+
- '3.2'
18+
- '3.3'
1819
gemfile:
19-
- rails_5.0
20-
- rails_5.1
21-
- rails_5.2
2220
- rails_6.0
2321
- rails_6.1
2422
- rails_7.0
25-
exclude:
26-
# Ruby >= 3.0 is supported since Rails 6.0
27-
- ruby: '3.0'
28-
gemfile: rails_5.0
29-
- ruby: '3.0'
30-
gemfile: rails_5.1
31-
- ruby: '3.0'
32-
gemfile: rails_5.2
33-
- ruby: '3.1'
34-
gemfile: rails_5.0
35-
- ruby: '3.1'
36-
gemfile: rails_5.1
37-
- ruby: '3.1'
38-
gemfile: rails_5.2
39-
# Rails 7.0 supports Ruby >= 2.7 only
40-
- ruby: '2.6'
41-
gemfile: rails_7.0
23+
- rails_7.1
4224
name: Run test with Ruby ${{ matrix.ruby }} and Gemfile ${{ matrix.gemfile }}
4325
services:
4426
mysql:
45-
image: mysql:5.7
27+
image: mysql:8.4
4628
env:
4729
MYSQL_ALLOW_EMPTY_PASSWORD: '1'
4830
MYSQL_DATABASE: blouson
@@ -56,7 +38,7 @@ jobs:
5638
env:
5739
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
5840
steps:
59-
- uses: actions/checkout@v3
41+
- uses: actions/checkout@v4
6042
- uses: ruby/setup-ruby@v1
6143
with:
6244
ruby-version: ${{ matrix.ruby }}

‎Appraisals

+4-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
appraise 'rails-5.0' do
2-
gem 'rails', '~> 5.0.0'
3-
end
4-
5-
appraise 'rails-5.1' do
6-
gem 'rails', '~> 5.1.0'
7-
end
8-
9-
appraise 'rails-5.2' do
10-
gem 'rails', '~> 5.2.0'
11-
end
12-
131
appraise 'rails-6.0' do
142
gem 'rails', '~> 6.0.0'
153
end
@@ -22,4 +10,8 @@ appraise 'rails-7.0' do
2210
gem 'rails', '~> 7.0.0'
2311
end
2412

13+
appraise 'rails-7.1' do
14+
gem 'rails', '~> 7.1.0'
15+
end
16+
2517
# vim: set ft=ruby:

‎blouson.gemspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
2121
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
2222
spec.require_paths = ["lib"]
2323

24-
spec.add_dependency 'rails', '>= 4.0.0'
24+
spec.add_dependency 'rails', '>= 6.0.0'
2525

2626
spec.add_development_dependency 'arproxy'
2727
spec.add_development_dependency 'mysql2'

‎gemfiles/rails_5.1.gemfile

-7
This file was deleted.

‎gemfiles/rails_5.2.gemfile

-7
This file was deleted.

‎gemfiles/rails_5.0.gemfile ‎gemfiles/rails_7.1.gemfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
source "https://rubygems.org"
44

5-
gem "rails", "~> 5.0.0"
5+
gem "rails", "~> 7.1.0"
66

77
gemspec path: "../"

‎lib/blouson/engine.rb

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ class Engine < Rails::Engine
1919
ActiveRecord::StatementInvalid.class_eval do
2020
prepend Blouson::SensitiveQueryFilter::StatementInvalidErrorFilter
2121
end
22+
if Rails::VERSION::MAJOR >= 7 && Rails::VERSION::MINOR >= 1 && defined?(Mysql2::Error)
23+
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
24+
prepend Blouson::SensitiveQueryFilter::AbstractAdapterFilter
25+
end
26+
end
2227
end
2328
end
2429
end

‎lib/blouson/sensitive_query_filter.rb

+39-14
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,43 @@ def self.filter_sensitive_words(message)
1515
end
1616

1717
module StatementInvalidErrorFilter
18-
def initialize(message = nil, original_exception = nil, sql: nil, binds: nil)
19-
if SensitiveQueryFilter.contain_sensitive_query?(message) || (SensitiveQueryFilter.contain_sensitive_query?(sql))
18+
def initialize(message = nil, sql: nil, binds: nil, connection_pool: nil)
19+
if SensitiveQueryFilter.contain_sensitive_query?(message) || SensitiveQueryFilter.contain_sensitive_query?(sql)
2020
message = SensitiveQueryFilter.filter_sensitive_words(message) if message
2121
sql = SensitiveQueryFilter.filter_sensitive_words(sql) if sql
2222
if defined?(Mysql2::Error)
23-
if original_exception.is_a?(Mysql2::Error)
24-
original_exception.extend(Mysql2Filter)
25-
elsif $!.is_a?(Mysql2::Error)
23+
if $!.is_a?(Mysql2::Error)
2624
$!.extend(Mysql2Filter)
2725
end
2826
end
2927
end
3028

31-
if original_exception
32-
# Rails < 5.0
33-
super(message, original_exception)
34-
elsif sql
29+
if connection_pool
30+
# Rails >= 7.1
31+
#
32+
# - https://github.com/rails/rails/pull/48295
33+
super(message, sql: sql, binds: binds, connection_pool: connection_pool)
34+
else
3535
# Rails >= 6.0
3636
#
3737
# - https://github.com/rails/rails/pull/34468
3838
super(message, sql: sql, binds: binds)
39+
end
40+
end
41+
42+
def set_query(sql, binds)
43+
if SensitiveQueryFilter.contain_sensitive_query?(sql)
44+
super(SensitiveQueryFilter.filter_sensitive_words(sql), binds)
3945
else
40-
# Rails >= 5.0
41-
#
42-
# - https://github.com/rails/rails/pull/18774
43-
# - https://github.com/rails/rails/pull/27503
44-
super(message)
46+
super(sql, binds)
47+
end
48+
end
49+
50+
def to_s
51+
if SensitiveQueryFilter.contain_sensitive_query?(sql)
52+
SensitiveQueryFilter.filter_sensitive_words(super)
53+
else
54+
super
4555
end
4656
end
4757
end
@@ -51,5 +61,20 @@ def message
5161
SensitiveQueryFilter.filter_sensitive_words(super)
5262
end
5363
end
64+
65+
module AbstractAdapterFilter
66+
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block)
67+
super(sql, name, binds, type_casted_binds, statement_name, async: false, &block)
68+
rescue ActiveRecord::RecordNotUnique, Mysql2::Error => ex
69+
if ex.cause.is_a?(Mysql2::Error)
70+
ex.cause.extend(Mysql2Filter)
71+
elsif $!.is_a?(Mysql2::Error)
72+
$!.extend(Mysql2Filter)
73+
end
74+
raise ex
75+
end
76+
77+
private :log
78+
end
5479
end
5580
end

‎spec/blouson/sensitive_query_filter_spec.rb

+28-35
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
11
require 'spec_helper'
22

3+
if ActiveRecord.version >= Gem::Version.new('7.1') && defined?(Mysql2::Error)
4+
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
5+
prepend Blouson::SensitiveQueryFilter::AbstractAdapterFilter
6+
end
7+
end
8+
9+
ActiveRecord::StatementInvalid.class_eval do
10+
prepend Blouson::SensitiveQueryFilter::StatementInvalidErrorFilter
11+
end
12+
313
RSpec.describe Blouson::SensitiveQueryFilter do
414
describe 'StatementInvalidErrorFilter' do
5-
def error
6-
model_class.where(condition).first
7-
rescue => e
8-
return e
9-
end
10-
11-
before do
12-
dummy_error = Class.new(ActiveRecord::StatementInvalid) do
13-
prepend Blouson::SensitiveQueryFilter::StatementInvalidErrorFilter
14-
end
15-
stub_const('ActiveRecord::StatementInvalid', dummy_error)
16-
end
15+
def error
16+
model_class.where(condition).first
17+
rescue => e
18+
return e
19+
end
1720

1821
context 'with query to sensitive table' do
1922
let(:model_class) { SecureUser }
2023
let(:email) { 'alice@example.com' }
2124
let(:condition) { { invalid_column: email } }
2225

2326
it 'filters SQL statement' do
24-
if Rails::VERSION::MAJOR >= 6
27+
if ActiveRecord::VERSION::MAJOR >= 6
2528
expect { model_class.where(condition).first }.to raise_error(/\[FILTERED\]/)
2629
else
2730
expect { model_class.where(condition).first }.to raise_error(/SELECT.*\[FILTERED\]/)
2831
end
2932
end
3033

3134
it 'filters to_s message' do
32-
if Rails::VERSION::MAJOR >= 6
35+
if ActiveRecord::VERSION::MAJOR >= 6
3336
expect(error.to_s).not_to include(email)
3437
expect(error.to_s).to include('[FILTERED]')
3538
else
@@ -40,7 +43,7 @@ def error
4043
end
4144

4245
it 'filters inspect message' do
43-
if Rails::VERSION::MAJOR >= 6
46+
if ActiveRecord::VERSION::MAJOR >= 6
4447
expect(error.inspect).to include('[FILTERED]')
4548
else
4649
expect(error.to_s).to include('SELECT')
@@ -49,7 +52,7 @@ def error
4952
end
5053
end
5154

52-
if Rails::VERSION::MAJOR >= 6
55+
if ActiveRecord::VERSION::MAJOR >= 6
5356
it 'filters sql message' do
5457
expect(error.sql).to include('SELECT')
5558
expect(error.sql).not_to include(email)
@@ -64,7 +67,7 @@ def error
6467
rescue => e
6568
error = e
6669
end
67-
if Rails::VERSION::MAJOR >= 6
70+
if ActiveRecord::VERSION::MAJOR >= 6
6871
expect(error.to_s).not_to include(email)
6972
expect(error.to_s).to include('[FILTERED]')
7073

@@ -82,7 +85,7 @@ def error
8285
let(:email) { "'alice'@example'.com''" }
8386

8487
it 'filters sensitive data' do
85-
if Rails::VERSION::MAJOR >= 6
88+
if ActiveRecord::VERSION::MAJOR >= 6
8689
expect(error.to_s).not_to include('alice')
8790

8891
expect(error.sql).to include('SELECT')
@@ -101,7 +104,7 @@ def error
101104
let(:condition) { { invalid_column: email, email2: email } }
102105

103106
it 'filters sensitive data' do
104-
if Rails::VERSION::MAJOR >= 6
107+
if ActiveRecord::VERSION::MAJOR >= 6
105108
expect(error.to_s).not_to include('alice')
106109

107110
expect(error.sql).to include('SELECT')
@@ -119,11 +122,6 @@ def error
119122

120123
context 'with sensitive value in Mysql2::Error' do
121124
before do
122-
dummy_error = Class.new(ActiveRecord::RecordNotUnique) do
123-
prepend Blouson::SensitiveQueryFilter::StatementInvalidErrorFilter
124-
end
125-
stub_const('ActiveRecord::RecordNotUnique', dummy_error)
126-
127125
model_class.create!(email: email, email2: email)
128126
end
129127

@@ -134,7 +132,7 @@ def error
134132
it 'filters sensitive data' do
135133
expect { model_class.create!(email: email, email2: email) }.to raise_error { |e|
136134
expect(e).to be_a(ActiveRecord::RecordNotUnique)
137-
if Rails::VERSION::MAJOR >= 6
135+
if ActiveRecord::VERSION::MAJOR >= 6
138136
expect(e.message).to_not include('alice')
139137

140138
expect(e.sql).to include('INSERT INTO `secure_users` ')
@@ -162,7 +160,7 @@ def error
162160
let(:condition) { { invalid_column: name } }
163161

164162
it 'does not filter SQL statement' do
165-
if Rails::VERSION::MAJOR >= 6
163+
if ActiveRecord::VERSION::MAJOR >= 6
166164
expect { model_class.where(condition).first }.to raise_error(/Unknown column 'users.invalid_column'/)
167165
else
168166
expect { model_class.where(condition).first }.to raise_error(/Unknown column 'users.invalid_column'/)
@@ -171,7 +169,7 @@ def error
171169
end
172170

173171
it 'does not filter to_s' do
174-
if Rails::VERSION::MAJOR >= 6
172+
if ActiveRecord::VERSION::MAJOR >= 6
175173
expect(error.to_s).not_to include('[FILTERED]')
176174
else
177175
expect(error.to_s).to include('SELECT')
@@ -181,7 +179,7 @@ def error
181179
end
182180

183181
it 'does not filter inspect message' do
184-
if Rails::VERSION::MAJOR >= 6
182+
if ActiveRecord::VERSION::MAJOR >= 6
185183
expect(error.inspect).not_to include('[FILTERED]')
186184
else
187185
expect(error.to_s).to include('SELECT')
@@ -190,7 +188,7 @@ def error
190188
end
191189
end
192190

193-
if Rails::VERSION::MAJOR >= 6
191+
if ActiveRecord::VERSION::MAJOR >= 6
194192
it 'does not filter sql message' do
195193
expect(error.sql).to include('SELECT')
196194
expect(error.sql).to include(name)
@@ -200,11 +198,6 @@ def error
200198

201199
context 'with non-sensitive value in Mysql2::Error' do
202200
before do
203-
dummy_error = Class.new(ActiveRecord::RecordNotUnique) do
204-
prepend Blouson::SensitiveQueryFilter::StatementInvalidErrorFilter
205-
end
206-
stub_const('ActiveRecord::RecordNotUnique', dummy_error)
207-
208201
model_class.create!(name: name)
209202
end
210203

@@ -216,7 +209,7 @@ def error
216209
expect { model_class.create!(name: name) }.to raise_error { |e|
217210
expect(e).to be_a(ActiveRecord::RecordNotUnique)
218211

219-
if Rails::VERSION::MAJOR >= 6
212+
if ActiveRecord::VERSION::MAJOR >= 6
220213
expect(e.message).to include(name)
221214
expect(e.message).to_not include('[FILTERED]')
222215

0 commit comments

Comments
 (0)
Please sign in to comment.