diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..7921bd0 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.4.8 diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..7ea6f0f --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +ruby 3.4.8 +bundler 4.0.7 diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d4624..d0b3938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG +## 2.0.0 + + - **BREAKING**: Removed Google Drive export feature and `google_drive` gem dependency. The `drive` action, `google_client` helper, `:google_api_id` and `:google_api_secret` config keys, and the `Dbhero::GdriveExporter` class are all gone. This unblocks Faraday 2.x compatibility, since `google_drive` transitively required `google-api-client 0.7.x` which hardcoded the removed `faraday/request/multipart` path. + - **BREAKING**: Minimum Rails bumped from `>= 4.1` to `>= 7.2`. + - **BREAKING**: Minimum Ruby set to `>= 3.4`. + - Dropped `codeclimate-test-reporter` (abandoned project). + - Migrated test stack from `factory_girl_rails` to `factory_bot_rails` and bumped `rspec-rails` from `~> 3.0` to `~> 7.0`. + - Modernized `spec/dummy` Rails application for Rails 7.2+ defaults. + ## 1.3.0 - Rails 5 Upgrade updates: diff --git a/Gemfile.lock b/Gemfile.lock index 384b07f..b03a21e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,10 @@ PATH remote: . specs: - dbhero (1.1.12) - google_drive (~> 1.0.4) + dbhero (2.0.0) + csv has_scope - rails (>= 4.1) + rails (>= 7.2) responders sass-rails slim-rails @@ -12,226 +12,414 @@ PATH GEM remote: https://rubygems.org/ specs: - actionmailer (4.2.1) - actionpack (= 4.2.1) - actionview (= 4.2.1) - activejob (= 4.2.1) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.1) - actionview (= 4.2.1) - activesupport (= 4.2.1) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.1) - actionview (4.2.1) - activesupport (= 4.2.1) + action_text-trix (2.1.19) + railties + actioncable (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + mail (>= 2.8.0) + actionmailer (8.1.3) + actionpack (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activesupport (= 8.1.3) + mail (>= 2.8.0) + rails-dom-testing (~> 2.2) + actionpack (8.1.3) + actionview (= 8.1.3) + activesupport (= 8.1.3) + nokogiri (>= 1.8.5) + 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 (8.1.3) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (8.1.3) + activesupport (= 8.1.3) builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.1) - activejob (4.2.1) - activesupport (= 4.2.1) - globalid (>= 0.3.0) - activemodel (4.2.1) - activesupport (= 4.2.1) - builder (~> 3.1) - activerecord (4.2.1) - activemodel (= 4.2.1) - activesupport (= 4.2.1) - arel (~> 6.0) - activesupport (4.2.1) - i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - addressable (2.4.0) - arel (6.0.3) - autoparse (0.3.3) - addressable (>= 2.3.1) - extlib (>= 0.9.15) - multi_json (>= 1.0.0) - builder (3.2.2) - codeclimate-test-reporter (0.4.7) - simplecov (>= 0.7.1, < 1.0.0) - concurrent-ruby (1.0.2) - diff-lcs (1.2.5) - docile (1.1.5) - erubis (2.7.0) - extlib (0.9.16) - factory_girl (4.5.0) - activesupport (>= 3.0.0) - factory_girl_rails (4.5.0) - factory_girl (~> 4.5.0) - railties (>= 3.0.0) - faraday (0.9.2) - multipart-post (>= 1.2, < 3) - globalid (0.3.6) - activesupport (>= 4.1.0) - google-api-client (0.8.6) - activesupport (>= 3.2) - addressable (~> 2.3) - autoparse (~> 0.3) - extlib (~> 0.9) - faraday (~> 0.9) - googleauth (~> 0.3) - launchy (~> 2.4) - multi_json (~> 1.10) - retriable (~> 1.4) - signet (~> 0.6) - google_drive (1.0.6) - google-api-client (>= 0.7.0, < 0.9) - nokogiri (>= 1.4.4, != 1.5.2, != 1.5.1) - oauth (>= 0.3.6) - oauth2 (>= 0.5.0) - googleauth (0.5.1) - faraday (~> 0.9) - jwt (~> 1.4) - logging (~> 2.0) - memoist (~> 0.12) - multi_json (~> 1.11) - os (~> 0.9) - signet (~> 0.7) - has_scope (0.6.0) - actionpack (>= 3.2, < 5) - activesupport (>= 3.2, < 5) - i18n (0.7.0) - json (1.8.2) - jwt (1.5.4) - launchy (2.4.3) - addressable (~> 2.3) - little-plugger (1.1.4) - logging (2.1.0) - little-plugger (~> 1.1) - multi_json (~> 1.10) - loofah (2.0.2) - nokogiri (>= 1.5.9) - mail (2.6.4) - mime-types (>= 1.16, < 4) - memoist (0.14.0) - mime-types (3.0) - mime-types-data (~> 3.2015) - mime-types-data (3.2016.0221) - mini_portile (0.6.2) - minitest (5.6.1) - multi_json (1.12.1) - multi_xml (0.5.5) - multipart-post (2.0.0) - nokogiri (1.6.6.2) - mini_portile (~> 0.6.0) - oauth (0.5.1) - oauth2 (1.2.0) - faraday (>= 0.8, < 0.10) - jwt (~> 1.0) - multi_json (~> 1.3) - multi_xml (~> 0.5) - rack (>= 1.2, < 3) - os (0.9.6) - pg (0.18.1) - rack (1.6.1) - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.1) - actionmailer (= 4.2.1) - actionpack (= 4.2.1) - actionview (= 4.2.1) - activejob (= 4.2.1) - activemodel (= 4.2.1) - activerecord (= 4.2.1) - activesupport (= 4.2.1) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.1) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.6) - activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) - rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.2) - loofah (~> 2.0) - railties (4.2.1) - actionpack (= 4.2.1) - activesupport (= 4.2.1) - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rake (10.4.2) - responders (2.1.1) - railties (>= 4.2.0, < 5.1) - retriable (1.4.1) - rspec-core (3.2.3) - rspec-support (~> 3.2.0) - rspec-expectations (3.2.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (8.1.3) + activesupport (= 8.1.3) + globalid (>= 0.3.6) + activemodel (8.1.3) + activesupport (= 8.1.3) + activerecord (8.1.3) + activemodel (= 8.1.3) + activesupport (= 8.1.3) + timeout (>= 0.4.0) + activestorage (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activesupport (= 8.1.3) + marcel (~> 1.0) + activesupport (8.1.3) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + base64 (0.3.0) + bigdecimal (4.1.2) + builder (3.3.0) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) + crass (1.0.6) + csv (3.3.5) + date (3.5.1) + diff-lcs (1.6.2) + drb (2.2.3) + erb (6.0.4) + erubi (1.13.1) + factory_bot (6.6.0) + activesupport (>= 6.1.0) + factory_bot_rails (6.5.1) + factory_bot (~> 6.5) + railties (>= 6.1.0) + ffi (1.17.4-aarch64-linux-gnu) + ffi (1.17.4-aarch64-linux-musl) + ffi (1.17.4-arm-linux-gnu) + ffi (1.17.4-arm-linux-musl) + ffi (1.17.4-arm64-darwin) + ffi (1.17.4-x86_64-darwin) + ffi (1.17.4-x86_64-linux-gnu) + ffi (1.17.4-x86_64-linux-musl) + globalid (1.3.0) + activesupport (>= 6.1) + has_scope (0.9.0) + actionpack (>= 7.0) + activesupport (>= 7.0) + i18n (1.14.8) + concurrent-ruby (~> 1.0) + io-console (0.8.2) + irb (1.18.0) + pp (>= 0.6.0) + prism (>= 1.3.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.19.5) + logger (1.7.0) + loofah (2.25.1) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.9.0) + logger + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.1.1) + mini_mime (1.1.5) + minitest (6.0.6) + drb (~> 2.0) + prism (~> 1.5) + net-imap (0.6.4) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.5) + nokogiri (1.19.3-aarch64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.3-aarch64-linux-musl) + racc (~> 1.4) + nokogiri (1.19.3-arm-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.3-arm-linux-musl) + racc (~> 1.4) + nokogiri (1.19.3-arm64-darwin) + racc (~> 1.4) + nokogiri (1.19.3-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.19.3-x86_64-linux-gnu) + racc (~> 1.4) + nokogiri (1.19.3-x86_64-linux-musl) + racc (~> 1.4) + pg (1.6.3) + pg (1.6.3-aarch64-linux) + pg (1.6.3-aarch64-linux-musl) + pg (1.6.3-arm64-darwin) + pg (1.6.3-x86_64-darwin) + pg (1.6.3-x86_64-linux) + pg (1.6.3-x86_64-linux-musl) + pp (0.6.3) + prettyprint + prettyprint (0.2.0) + prism (1.9.0) + psych (5.3.1) + date + stringio + racc (1.8.1) + rack (3.2.6) + rack-session (2.1.2) + base64 (>= 0.1.0) + rack (>= 3.0.0) + rack-test (2.2.0) + rack (>= 1.3) + rackup (2.3.1) + rack (>= 3) + rails (8.1.3) + actioncable (= 8.1.3) + actionmailbox (= 8.1.3) + actionmailer (= 8.1.3) + actionpack (= 8.1.3) + actiontext (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activemodel (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) + bundler (>= 1.15.0) + railties (= 8.1.3) + rails-dom-testing (2.3.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.7.0) + loofah (~> 2.25) + 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) + railties (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) + irb (~> 1.13) + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + tsort (>= 0.2) + zeitwerk (~> 2.6) + rake (13.4.2) + rdoc (7.2.0) + erb + psych (>= 4.0.0) + tsort + reline (0.6.3) + io-console (~> 0.5) + responders (3.2.0) + actionpack (>= 7.0) + railties (>= 7.0) + rspec-core (3.13.6) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) - rspec-mocks (3.2.1) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) - rspec-rails (3.2.1) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.2.0) - rspec-expectations (~> 3.2.0) - rspec-mocks (~> 3.2.0) - rspec-support (~> 3.2.0) - rspec-support (3.2.2) - sass (3.4.22) - sass-rails (5.0.5) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - shoulda (3.5.0) - shoulda-context (~> 1.0, >= 1.0.1) - shoulda-matchers (>= 1.4.1, < 3.0) - shoulda-context (1.2.1) - shoulda-matchers (2.8.0) - activesupport (>= 3.0.0) - signet (0.7.3) - addressable (~> 2.3) - faraday (~> 0.9) - jwt (~> 1.5) - multi_json (~> 1.10) - simplecov (0.10.0) - docile (~> 1.1.0) - json (~> 1.8) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.0) - slim (3.0.7) - temple (~> 0.7.6) - tilt (>= 1.3.3, < 2.1) - slim-rails (3.1.0) + rspec-support (~> 3.13.0) + rspec-rails (7.1.1) + actionpack (>= 7.0) + activesupport (>= 7.0) + railties (>= 7.0) + rspec-core (~> 3.13) + rspec-expectations (~> 3.13) + rspec-mocks (~> 3.13) + rspec-support (~> 3.13) + rspec-support (3.13.7) + sass-rails (6.0.0) + sassc-rails (~> 2.1, >= 2.1.1) + sassc (2.4.0) + ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt + securerandom (0.4.1) + shoulda-matchers (7.0.1) + activesupport (>= 7.1) + slim (5.2.1) + temple (~> 0.10.0) + tilt (>= 2.1.0) + slim-rails (4.0.0) actionpack (>= 3.1) railties (>= 3.1) - slim (~> 3.0) - sprockets (3.6.0) + slim (>= 3.0, < 6.0, != 5.0.0) + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.0.4) - actionpack (>= 4.0) - activesupport (>= 4.0) + logger + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) - temple (0.7.7) - thor (0.19.1) - thread_safe (0.3.5) - tilt (2.0.2) - tzinfo (1.2.2) - thread_safe (~> 0.1) + stringio (3.2.0) + temple (0.10.4) + thor (1.5.0) + tilt (2.7.0) + timeout (0.6.1) + tsort (0.2.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uri (1.1.1) + useragent (0.16.11) + websocket-driver (0.8.0) + base64 + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.8.1) PLATFORMS - ruby + aarch64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + x86_64-darwin + x86_64-linux + x86_64-linux-gnu + x86_64-linux-musl DEPENDENCIES - codeclimate-test-reporter dbhero! - factory_girl_rails + factory_bot_rails pg - rspec-rails (~> 3.0) - shoulda + rspec-rails (~> 7.0) + shoulda-matchers + +CHECKSUMS + action_text-trix (2.1.19) sha256=7012f59421009cf284aa651294896414d653a61a2417c9b8714c8476d2f74009 + actioncable (8.1.3) sha256=e5bc7f75e44e6a22de29c4f43176927c3a9ce4824464b74ed18d8226e75a80f0 + actionmailbox (8.1.3) sha256=df7da474eaa0e70df4ed5a6fef66eb3b3b0f2dbf7f14518deee8d77f1b4aae59 + actionmailer (8.1.3) sha256=831f724891bb70d0aaa4d76581a6321124b6a752cb655c9346aae5479318448d + actionpack (8.1.3) sha256=af998cae4d47c5d581a2cc363b5c77eb718b7c4b45748d81b1887b25621c29a3 + actiontext (8.1.3) sha256=d291019c00e1ea9e6463011fa214f6081a56d7b9a1d224e7d3f6384c1dafc7d2 + actionview (8.1.3) sha256=1347c88c7f3edb38100c5ce0e9fb5e62d7755f3edc1b61cce2eb0b2c6ea2fd5d + activejob (8.1.3) sha256=a149b1766aa8204c3c3da7309e4becd40fcd5529c348cffbf6c9b16b565fe8d3 + activemodel (8.1.3) sha256=90c05cbe4cef3649b8f79f13016191ea94c4525ce4a5c0fb7ef909c4b91c8219 + activerecord (8.1.3) sha256=8003be7b2466ba0a2a670e603eeb0a61dd66058fccecfc49901e775260ac70ab + activestorage (8.1.3) sha256=0564ce9309143951a67615e1bb4e090ee54b8befed417133cae614479b46384d + activesupport (8.1.3) sha256=21a5e0dfbd4c3ddd9e1317ec6a4d782fa226e7867dc70b0743acda81a1dca20e + base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b + bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd + builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f + concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab + connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a + crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d + csv (3.3.5) sha256=6e5134ac3383ef728b7f02725d9872934f523cb40b961479f69cf3afa6c8e73f + date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0 + dbhero (2.0.0) + diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962 + drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 + erb (6.0.4) sha256=38e3803694be357fe2bfe312487c74beaf9fb4e5beb3e22498952fe1645b95d9 + erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9 + factory_bot (6.6.0) sha256=1fc1b3b5620ec980a6a27aec1b6ec8c250ca82962e970e8a40f93e8d388d4b89 + factory_bot_rails (6.5.1) sha256=d3cc4851eae4dea8a665ec4a4516895045e710554d2b5ac9e68b94d351bc6d68 + ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df + ffi (1.17.4-aarch64-linux-musl) sha256=9286b7a615f2676245283aef0a0a3b475ae3aae2bb5448baace630bb77b91f39 + ffi (1.17.4-arm-linux-gnu) sha256=d6dbddf7cb77bf955411af5f187a65b8cd378cb003c15c05697f5feee1cb1564 + ffi (1.17.4-arm-linux-musl) sha256=9d4838ded0465bef6e2426935f6bcc93134b6616785a84ffd2a3d82bc3cf6f95 + ffi (1.17.4-arm64-darwin) sha256=19071aaf1419251b0a46852abf960e77330a3b334d13a4ab51d58b31a937001b + ffi (1.17.4-x86_64-darwin) sha256=aa70390523cf3235096cf64962b709b4cfbd5c082a2cb2ae714eb0fe2ccda496 + ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d + ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e + globalid (1.3.0) sha256=05c639ad6eb4594522a0b07983022f04aa7254626ab69445a0e493aa3786ff11 + has_scope (0.9.0) sha256=783a93006cf898525bb4899696f1d088c0f6ff897d6df2bf03fdbbe0d0b5124c + i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5 + io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc + irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3 + json (2.19.5) sha256=218a18553e4801d579ca7e0f5bc72bafd776d7397238a1fb4e74db5b0a812c59 + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 + loofah (2.25.1) sha256=d436c73dbd0c1147b16c4a41db097942d217303e1f7728704b37e4df9f6d2e04 + mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941 + marcel (1.1.1) sha256=16eb578814fc914a43a48887189568f9eb9a2de8274313050c2b00f0018614f7 + mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef + minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1 + net-imap (0.6.4) sha256=9a5598c67a3022c284d98430ef1d4948e7dbdb62596f61081ea8ca933270a02b + net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3 + net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8 + net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736 + nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1 + nokogiri (1.19.3-aarch64-linux-gnu) sha256=46b89e5d7b9e844c2ee360794240c6ea2a4e6fa0c5892a4ed487db621224b639 + nokogiri (1.19.3-aarch64-linux-musl) sha256=8392dfdcd21be7a94dbbe9ccc138dea01b97b24cb2dc02a114ca98bfb1d9a0b7 + nokogiri (1.19.3-arm-linux-gnu) sha256=3919d5ffc334ad778a4a9eb88fda7dcb8b1fb58c8a52ac640c6dcd2f038e774f + nokogiri (1.19.3-arm-linux-musl) sha256=9ce1cb6346bb9c67b1550eb537aa183ead91e4b6eadb2f36ade02d8dd2a79fb6 + nokogiri (1.19.3-arm64-darwin) sha256=71b9bd424b1b7abc18b05052a1a3cfd3627abdca62be280854cc411791357e42 + nokogiri (1.19.3-x86_64-darwin) sha256=77f3fba57d46c53ab31e62fc6c28f705109d1bf6264356c76f132b2be5728d4d + nokogiri (1.19.3-x86_64-linux-gnu) sha256=2f5078620fe12e83669b5b17311b32532a8153d02eee7ad06948b926d6080976 + nokogiri (1.19.3-x86_64-linux-musl) sha256=248c906d2166eca5efb56d52fdee5f9a1f51d69a72e2b64fdac647b4ce39ea3f + pg (1.6.3) sha256=1388d0563e13d2758c1089e35e973a3249e955c659592d10e5b77c468f628a99 + pg (1.6.3-aarch64-linux) sha256=0698ad563e02383c27510b76bf7d4cd2de19cd1d16a5013f375dd473e4be72ea + pg (1.6.3-aarch64-linux-musl) sha256=06a75f4ea04b05140146f2a10550b8e0d9f006a79cdaf8b5b130cde40e3ecc2c + pg (1.6.3-arm64-darwin) sha256=7240330b572e6355d7c75a7de535edb5dfcbd6295d9c7777df4d9dddfb8c0e5f + pg (1.6.3-x86_64-darwin) sha256=ee2e04a17c0627225054ffeb43e31a95be9d7e93abda2737ea3ce4a62f2729d6 + pg (1.6.3-x86_64-linux) sha256=5d9e188c8f7a0295d162b7b88a768d8452a899977d44f3274d1946d67920ae8d + pg (1.6.3-x86_64-linux-musl) sha256=9c9c90d98c72f78eb04c0f55e9618fe55d1512128e411035fe229ff427864009 + pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6 + prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193 + prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85 + psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974 + racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f + rack (3.2.6) sha256=5ed78e1f73b2e25679bec7d45ee2d4483cc4146eb1be0264fc4d94cb5ef212c2 + rack-session (2.1.2) sha256=595434f8c0c3473ae7d7ac56ecda6cc6dfd9d37c0b2b5255330aa1576967ffe8 + rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463 + rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868 + rails (8.1.3) sha256=6d017ba5348c98fc909753a8169b21d44de14d2a0b92d140d1a966834c3c9cd3 + rails-dom-testing (2.3.0) sha256=8acc7953a7b911ca44588bf08737bc16719f431a1cc3091a292bca7317925c1d + rails-html-sanitizer (1.7.0) sha256=28b145cceaf9cc214a9874feaa183c3acba036c9592b19886e0e45efc62b1e89 + railties (8.1.3) sha256=913eb0e0cb520aac687ffd74916bd726d48fa21f47833c6292576ef6a286de22 + rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701 + rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192 + reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835 + responders (3.2.0) sha256=89c2d6ac0ae16f6458a11524cae4a8efdceba1a3baea164d28ee9046bd3df55a + rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d + rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836 + rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47 + rspec-rails (7.1.1) sha256=e15dccabed211e2fd92f21330c819adcbeb1591c1d66c580d8f2d8288557e331 + rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c + sass-rails (6.0.0) sha256=e0b6448ea1c7929fd5929fc7a8eb2d78045e44cc82fc0765a249d3fa1c5810d3 + sassc (2.4.0) sha256=4c60a2b0a3b36685c83b80d5789401c2f678c1652e3288315a1551d811d9f83e + sassc-rails (2.1.2) sha256=5f4fdf3881fc9bdc8e856ffbd9850d70a2878866feae8114aa45996179952db5 + securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 + shoulda-matchers (7.0.1) sha256=b4bfd8744c10e0a36c8ac1a687f921ee7e25ed529e50488d61b79a8688749c77 + slim (5.2.1) sha256=72351dff7e2ff20e2d5c393cfc385bb9142cef5db059141628fd7163ac3c13e7 + slim-rails (4.0.0) sha256=2cfee5c4ba00d4d935676db1e74a05dbaf9dd6f789903a1006e3bb687bbe36e2 + sprockets (4.2.2) sha256=761e5a49f1c288704763f73139763564c845a8f856d52fba013458f8af1b59b1 + sprockets-rails (3.5.2) sha256=a9e88e6ce9f8c912d349aa5401509165ec42326baf9e942a85de4b76dbc4119e + stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1 + temple (0.10.4) sha256=b7a1e94b6f09038ab0b6e4fe0126996055da2c38bec53a8a336f075748fff72c + thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73 + tilt (2.7.0) sha256=0d5b9ba69f6a36490c64b0eee9f6e9aad517e20dcc848800a06eb116f08c6ab3 + timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb + tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f + tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b + uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6 + useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844 + websocket-driver (0.8.0) sha256=ed0dba4b943c22f17f9a734817e808bc84cdce6a7e22045f5315aa57676d4962 + websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241 + zeitwerk (2.8.1) sha256=1c85e0f28954d68cd16e575da37f26846f609b68d80b5942ccfd31030c2449d5 BUNDLED WITH - 1.12.5 + 4.0.9 diff --git a/app/controllers/dbhero/application_controller.rb b/app/controllers/dbhero/application_controller.rb index cf2d7a3..fcff7ef 100644 --- a/app/controllers/dbhero/application_controller.rb +++ b/app/controllers/dbhero/application_controller.rb @@ -1,12 +1,10 @@ module Dbhero class ApplicationController < ActionController::Base - def check_auth - if Dbhero.authenticate - unless _current_user && call_custom_auth && _current_user.has_role?(:super_admin) - render status: :forbidden, file: "#{Rails.root}/public/403" - end - end + return unless Dbhero.authenticate + return if _current_user && call_custom_auth + + head :forbidden end def user_representation @@ -14,18 +12,16 @@ def user_representation end def _current_user - if Dbhero.authenticate && Dbhero.current_user_method.present? - send(Dbhero.current_user_method) - end + return unless Dbhero.authenticate && Dbhero.current_user_method.present? + + send(Dbhero.current_user_method) end def call_custom_auth cond = Dbhero.custom_user_auth_condition - if cond.present? && cond.is_a?(Proc) - cond.call(_current_user) - else - true - end + return true unless cond.is_a?(Proc) + + cond.call(_current_user) end end end diff --git a/app/controllers/dbhero/dataclips_controller.rb b/app/controllers/dbhero/dataclips_controller.rb index 66da0d6..f4b2e9c 100644 --- a/app/controllers/dbhero/dataclips_controller.rb +++ b/app/controllers/dbhero/dataclips_controller.rb @@ -1,7 +1,6 @@ require_dependency "dbhero/application_controller" require_dependency "responders" require_dependency "has_scope" -require_dependency "google_drive" module Dbhero class DataclipsController < ApplicationController @@ -14,16 +13,6 @@ def index @dataclips = apply_scopes(Dataclip.ordered) end - def drive - token = session.delete(:clip_token) - - google_client.fetch_access_token!(params[:code]) - google_client.options[:import_data_url] = dataclip_url(id: token, format: 'csv') - google_client.export_clip_by_token token - - redirect_to dataclip_path(google_client.dataclip, gdrive_file_url: google_client.exported_file_url) - end - def show check_auth if @dataclip.private? @dataclip.query_result @@ -31,11 +20,6 @@ def show respond_to do |format| format.html do return render :show, layout: false if request.xhr? - - if params[:export_gdrive] - session[:clip_token] = @dataclip.token - redirect_to google_client.auth.authorization_uri.to_s - end end format.csv do @@ -80,9 +64,5 @@ def set_dataclip def dataclip_params params.require(:dataclip).permit(:description, :raw_query, :private) end - - def google_client - @g_client ||= Dbhero::GdriveExporter.new(redirect_uri: drive_dataclips_url) - end end end diff --git a/app/models/dbhero/dataclip.rb b/app/models/dbhero/dataclip.rb index 648a2d8..3c276a1 100644 --- a/app/models/dbhero/dataclip.rb +++ b/app/models/dbhero/dataclip.rb @@ -45,16 +45,16 @@ def cached? end def query_result - DataclipRead.transaction do - begin - @q_result ||= Rails.cache.fetch("dataclip_#{self.token}", expires_in: (::Dbhero.cached_query_exp||10.minutes)) do - DataclipRead.connection.select_all(self.raw_query) - end - rescue => e - self.errors.add(:base, e.message) + DataclipRead.transaction(requires_new: true) do + @q_result ||= Rails.cache.fetch("dataclip_#{self.token}", expires_in: (::Dbhero.cached_query_exp || 10.minutes)) do + DataclipRead.connection.select_all(self.raw_query) end raise ActiveRecord::Rollback end + rescue => e + # Catches both errors from select_all and from a failed savepoint rollback + # (e.g. when user SQL contains COMMIT/ROLLBACK that ate the savepoint). + self.errors.add(:base, e.message) end def otq_result diff --git a/app/views/dbhero/dataclips/_clip_table.html.slim b/app/views/dbhero/dataclips/_clip_table.html.slim index e5e10c7..cb360c9 100644 --- a/app/views/dbhero/dataclips/_clip_table.html.slim +++ b/app/views/dbhero/dataclips/_clip_table.html.slim @@ -19,8 +19,6 @@ ul id='export-drop' class='dropdown-content' li = link_to 'csv', dataclip_path(@dataclip, format: 'csv') - /li - / = link_to 'google drive', dataclip_path(@dataclip, export_gdrive: true) .col.s12 style="overflow: auto;" table#clip_table.cell-border.striped data-page-length='300' diff --git a/app/views/dbhero/dataclips/show.html.slim b/app/views/dbhero/dataclips/show.html.slim index c35ad9b..a15fb59 100644 --- a/app/views/dbhero/dataclips/show.html.slim +++ b/app/views/dbhero/dataclips/show.html.slim @@ -7,12 +7,4 @@ .container - - if params[:gdrive_file_url].present? - .card-panel.teal.up.green.lighten-1 - .card-content.white-text.center-align style='text-transform: uppercase;' - | DATACLIP EXPORTED!  - strong - = link_to 'CLICK HERE TO VIEW IT', params[:gdrive_file_url], style: 'color: #33691e;' - - -== render 'clip_table' + == render 'clip_table' diff --git a/app/views/dbhero/one_time_query/_clip_table.html.slim b/app/views/dbhero/one_time_query/_clip_table.html.slim index e00e191..a081f8f 100644 --- a/app/views/dbhero/one_time_query/_clip_table.html.slim +++ b/app/views/dbhero/one_time_query/_clip_table.html.slim @@ -13,8 +13,6 @@ ul id='export-drop' class='dropdown-content' li = link_to 'csv', one_time_query_url(params: { dataclip: @dataclip_params }, format: 'csv') - /li - / = link_to 'google drive', dataclip_path(@dataclip, export_gdrive: true) .col.s12 style="overflow: auto;" table#clip_table.cell-border.striped data-page-length='300' diff --git a/config/routes.rb b/config/routes.rb index 9461499..1f26dcb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,6 @@ Dbhero::Engine.routes.draw do root to: "dataclips#index" - resources :dataclips do - get :drive, on: :collection - end + resources :dataclips get :one_time_query, to: "one_time_query#index" end diff --git a/dbhero.gemspec b/dbhero.gemspec index dcf9a79..d1e9387 100644 --- a/dbhero.gemspec +++ b/dbhero.gemspec @@ -18,16 +18,17 @@ Gem::Specification.new do |s| s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] s.test_files = Dir["spec/**/*"] - s.add_dependency "rails", ">= 4.1" + s.required_ruby_version = ">= 3.4" + + s.add_dependency "rails", ">= 7.2" s.add_dependency "responders" s.add_dependency "sass-rails" s.add_dependency "slim-rails" - s.add_dependency "google_drive", "~> 1.0.4" s.add_dependency "has_scope" + s.add_dependency "csv" # bundled-gem in Ruby 3.4+; required by Dbhero::Dataclip s.add_development_dependency "pg" - s.add_development_dependency 'rspec-rails', '~> 3.0' - s.add_development_dependency 'factory_girl_rails' - s.add_development_dependency 'codeclimate-test-reporter' - s.add_development_dependency 'shoulda' + s.add_development_dependency "rspec-rails", "~> 7.0" + s.add_development_dependency "factory_bot_rails" + s.add_development_dependency "shoulda-matchers" end diff --git a/lib/dbhero.rb b/lib/dbhero.rb index 7f40854..e979fb8 100644 --- a/lib/dbhero.rb +++ b/lib/dbhero.rb @@ -1,6 +1,6 @@ +require "dbhero/version" require "dbhero/engine" require "dbhero/configuration" -require "dbhero/gdrive_exporter" require "slim" module Dbhero diff --git a/lib/dbhero/configuration.rb b/lib/dbhero/configuration.rb index ea614da..903587f 100644 --- a/lib/dbhero/configuration.rb +++ b/lib/dbhero/configuration.rb @@ -1,19 +1,26 @@ +require "active_support/core_ext/numeric/time" + module Dbhero module Configuration - VALID_CONFIG_KEYS = [:authenticate, :current_user_method, :custom_user_auth_condition, :csv_delimiter, - :user_representation, :google_api_id, :google_api_secret, :max_rows_limit, :cached_query_exp].freeze + VALID_CONFIG_KEYS = [ + :authenticate, + :current_user_method, + :custom_user_auth_condition, + :csv_delimiter, + :user_representation, + :max_rows_limit, + :cached_query_exp + ].freeze DEFAULT_AUTHENTICATE = true DEFAULT_CURRENT_USER_METHOD = :current_user - DEFAULT_GOOGLE_API_ID = '' - DEFAULT_GOOGLE_API_SECRET = '' DEFAULT_USER_PRESENTATION = :email DEFAULT_CUSTOM_USER_AUTH_CONDITION = nil DEFAULT_MAX_ROWS_LIMIT = 10_000 DEFAULT_CSV_DELIMITER = ',' DEFAULT_CACHED_QUERY_EXP = 10.minutes - attr_accessor *VALID_CONFIG_KEYS + attr_accessor(*VALID_CONFIG_KEYS) def self.extended(base) base.reset @@ -24,21 +31,18 @@ def configure end def options - Hash[ * VALID_CONFIG_KEYS.map { |key| [key, send(key)] }.flatten ] + VALID_CONFIG_KEYS.each_with_object({}) { |key, h| h[key] = send(key) } end def reset self.authenticate = DEFAULT_AUTHENTICATE self.current_user_method = DEFAULT_CURRENT_USER_METHOD self.user_representation = DEFAULT_USER_PRESENTATION - self.google_api_id = DEFAULT_GOOGLE_API_ID - self.google_api_secret = DEFAULT_GOOGLE_API_SECRET self.custom_user_auth_condition = DEFAULT_CUSTOM_USER_AUTH_CONDITION self.max_rows_limit = DEFAULT_MAX_ROWS_LIMIT self.csv_delimiter = DEFAULT_CSV_DELIMITER self.cached_query_exp = DEFAULT_CACHED_QUERY_EXP end - end end diff --git a/lib/dbhero/gdrive_exporter.rb b/lib/dbhero/gdrive_exporter.rb deleted file mode 100644 index ed422dd..0000000 --- a/lib/dbhero/gdrive_exporter.rb +++ /dev/null @@ -1,46 +0,0 @@ -module Dbhero - class GdriveExporter - attr_accessor :options - attr_reader :client, :auth, :session, - :dataclip, :uploaded_file, :exported_file_url - - def initialize options = {} - @client ||= ::Google::APIClient.new - @options = options - - @auth = @client.authorization - @auth.client_id = Dbhero.google_api_id - @auth.client_secret = Dbhero.google_api_secret - @auth.scope = - "https://www.googleapis.com/auth/drive " + - "https://spreadsheets.google.com/feeds/" - - @auth.redirect_uri = options[:redirect_uri] - end - - def fetch_access_token! code - @auth.code = code - @auth.fetch_access_token! - @session ||= GoogleDrive.login_with_oauth(@auth.access_token) - end - - def export_clip_by_token token - @dataclip ||= Dataclip.find_by token: token - raise 'unable to find dataclip' unless @dataclip - - exported_file = find_or_create_spreadsheet! - @exported_file_url = exported_file.human_url - end - - private - - def find_or_create_spreadsheet! - file_title = "DBHero - #{@dataclip.title}" - spreadsheet = session.create_spreadsheet(file_title) - worksheet = spreadsheet.worksheets[0] - worksheet[1,1] = "=importData(\"#{@options[:import_data_url]}\")" - worksheet.save - spreadsheet - end - end -end diff --git a/lib/dbhero/version.rb b/lib/dbhero/version.rb index d601118..7ec8b00 100644 --- a/lib/dbhero/version.rb +++ b/lib/dbhero/version.rb @@ -1,3 +1,3 @@ module Dbhero - VERSION = "1.3.0" + VERSION = "2.0.0" end diff --git a/lib/generators/dbhero/install/templates/dbhero.rb b/lib/generators/dbhero/install/templates/dbhero.rb index 491ebc1..3a00484 100644 --- a/lib/generators/dbhero/install/templates/dbhero.rb +++ b/lib/generators/dbhero/install/templates/dbhero.rb @@ -19,13 +19,6 @@ # String representation for user # when creating a dataclip just save on user field config.user_representation = :email - - # Google drive integration, uncomment to use ;) - # you can get you google api credentials here: - # https://developers.google.com/drive/web/auth/web-server - # - # config.google_api_id = 'GOOGLE_API_ID' - # config.google_api_secret = 'GOOGLE_API_SECRET' end diff --git a/spec/controllers/dbhero/dataclips_controller_spec.rb b/spec/controllers/dbhero/dataclips_controller_spec.rb index 4dbc355..050c609 100644 --- a/spec/controllers/dbhero/dataclips_controller_spec.rb +++ b/spec/controllers/dbhero/dataclips_controller_spec.rb @@ -1,292 +1,162 @@ -require 'rails_helper' +require "rails_helper" -RSpec.shared_examples "user not authenticated" do - let(:method_name) { :get } - let(:options) { nil } - - before do - allow(Dbhero).to receive(:authenticate).and_return(true) - allow(controller).to receive(:_current_user).and_return(nil) - end - - it "should raise forbidden error" do - expect { - send(method_name, *options) - }.to raise_error(ActionController::RoutingError, 'Forbidden') - end -end - -RSpec.shared_examples "user authenticated" do - let(:method_name) { :get } - let(:options) { nil } - let(:expect_method) { :be_success } - - before do - current_user = double() - allow(current_user).to receive(:email).and_return('foo@bar.com') - allow(controller).to receive(:_current_user).and_return(current_user) - allow(Dbhero).to receive(:authenticate).and_return(true) - - send(method_name, *options) - end - - it("response should be success") { expect(response).to send(expect_method) } -end - -RSpec.shared_examples "user authenticated match for custom role" do - let(:method_name) { :get } - let(:options) { nil } - let(:expect_method) { :be_success } - - before do - current_user = double() - allow(current_user).to receive(:email).and_return('foo@bar.com') - allow(current_user).to receive(:admin?).and_return(true) - allow(controller).to receive(:_current_user).and_return(current_user) - allow(Dbhero).to receive(:authenticate).and_return(true) - allow(Dbhero).to receive(:custom_user_auth_condition).and_return(->(u){u.admin?}) - - send(method_name, *options) - end - - it("response should be success") { expect(response).to send(expect_method) } -end - -RSpec.shared_examples "user authenticated don't match for custom role" do - let(:method_name) { :get } - let(:options) { nil } - - before do - current_user = double() - allow(current_user).to receive(:email).and_return('foo@bar.com') - allow(current_user).to receive(:admin?).and_return(false) - allow(controller).to receive(:_current_user).and_return(current_user) - allow(Dbhero).to receive(:authenticate).and_return(true) - allow(Dbhero).to receive(:custom_user_auth_condition).and_return(->(u){u.admin?}) - end - - it "should raise forbidden error" do - expect { - send(method_name, *options) - }.to raise_error(ActionController::RoutingError, 'Forbidden') - end -end +RSpec.describe Dbhero::DataclipsController, type: :controller do + routes { Dbhero::Engine.routes } -RSpec.shared_examples "disabled auth" do - let(:method_name) { :get } - let(:options) { nil } - let(:expect_method) { :be_success } + let(:current_user) { double("user", email: "foo@bar.com") } - before do + def disable_authentication allow(Dbhero).to receive(:authenticate).and_return(false) allow(controller).to receive(:_current_user).and_return(nil) - send(method_name, *options) end - it("response should be success") { expect(response).to send(expect_method) } -end - -RSpec.describe Dbhero::DataclipsController, type: :controller do - routes { Dbhero::Engine.routes } + def authenticate_as(user, custom_auth: nil) + allow(Dbhero).to receive(:authenticate).and_return(true) + allow(controller).to receive(:_current_user).and_return(user) + allow(Dbhero).to receive(:custom_user_auth_condition).and_return(custom_auth) + end - describe "GET index" do - describe "with enabled auth" do - it_should_behave_like "user not authenticated" do - let(:options) { :index } + shared_examples "requires authentication" do |action, method: :get, action_params: {}| + context "with no current user" do + before do + allow(Dbhero).to receive(:authenticate).and_return(true) + allow(controller).to receive(:_current_user).and_return(nil) + public_send(method, action, params: action_params) end - it_should_behave_like "user authenticated" do - let(:options) { :index } - end + it { expect(response).to have_http_status(:forbidden) } + end - it_should_behave_like "user authenticated match for custom role" do - let(:options) { :index } + context "with current user and no custom auth" do + before do + authenticate_as(current_user) + public_send(method, action, params: action_params) end - it_should_behave_like "user authenticated don't match for custom role" do - let(:options) { :index } - end + it { expect(response).not_to have_http_status(:forbidden) } end - describe "with disabled auth" do - it_should_behave_like "disabled auth" do - let(:options) { :index } - end - end - end + context "with current user and passing custom auth" do + let(:admin) { double("admin", email: "a@b.com", admin?: true) } - describe "GET new" do - describe "with enabled auth" do - it_should_behave_like "user not authenticated" do - let(:options) { :new } + before do + authenticate_as(admin, custom_auth: ->(u) { u.admin? }) + public_send(method, action, params: action_params) end - it_should_behave_like "user authenticated" do - let(:options) { :new } - end + it { expect(response).not_to have_http_status(:forbidden) } + end - it_should_behave_like "user authenticated match for custom role" do - let(:options) { :new } - end + context "with current user and failing custom auth" do + let(:non_admin) { double("non_admin", email: "a@b.com", admin?: false) } - it_should_behave_like "user authenticated don't match for custom role" do - let(:options) { :new } + before do + authenticate_as(non_admin, custom_auth: ->(u) { u.admin? }) + public_send(method, action, params: action_params) end + + it { expect(response).to have_http_status(:forbidden) } end - describe "with disabled auth" do - it_should_behave_like "disabled auth" do - let(:options) { :new } + context "with authentication disabled" do + before do + disable_authentication + public_send(method, action, params: action_params) end + + it { expect(response).not_to have_http_status(:forbidden) } end end - describe "POST create" do - describe "with enabled auth" do - it_should_behave_like "user not authenticated" do - let(:method_name) { :post } - let(:options) { [:create, { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } }] } - end - - it_should_behave_like "user authenticated" do - let(:method_name) { :post } - let(:options) { [:create, { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } }] } - let(:expect_method) { :be_redirect } + describe "GET index" do + include_examples "requires authentication", :index + end - it { expect(Dbhero::Dataclip.find_by(description: 'foo bar')).not_to be_nil } - end + describe "GET new" do + include_examples "requires authentication", :new + end - it_should_behave_like "user authenticated match for custom role" do - let(:method_name) { :post } - let(:options) { [:create, { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } }] } - let(:expect_method) { :be_redirect } + describe "POST create" do + let(:valid_params) { { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } } } - it "find dataclip" do - clip = Dbhero::Dataclip.find_by(description: 'foo bar') + include_examples "requires authentication", :create, method: :post, action_params: { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } } - expect(clip.user).to eq(controller._current_user.email) - expect(clip.description).to eq("foo bar") - expect(clip.raw_query).to eq("select 'foo' as bar") - end - end + context "when authenticated" do + before { authenticate_as(current_user) } - it_should_behave_like "user authenticated don't match for custom role" do - let(:method_name) { :post } - let(:options) { [:create, { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } }] } + it "creates the dataclip" do + post :create, params: valid_params + clip = Dbhero::Dataclip.find_by(description: "foo bar") + expect(clip).not_to be_nil + expect(clip.user).to eq("foo@bar.com") + expect(clip.raw_query).to eq("select 'foo' as bar") end end - describe "with disabled auth" do - it_should_behave_like "disabled auth" do - let(:method_name) { :post } - let(:options) { [:create, { dataclip: { description: "foo bar disabled", raw_query: "select 'foo' as bar" } }] } - let(:expect_method) { :be_redirect } + context "when authentication is disabled" do + before { disable_authentication } - it "find dataclip" do - clip = Dbhero::Dataclip.find_by(description: 'foo bar disabled') - - expect(clip.user).to be_nil - expect(clip.description).to eq("foo bar disabled") - expect(clip.raw_query).to eq("select 'foo' as bar") - end + it "creates the dataclip with no user" do + post :create, params: { dataclip: { description: "anonymous", raw_query: "select 1" } } + clip = Dbhero::Dataclip.find_by(description: "anonymous") + expect(clip).not_to be_nil + expect(clip.user).to be_nil end end end - describe "GET edit" do - describe "with enabled auth" do - it_should_behave_like "user not authenticated" do - let(:dataclip) { create(:dataclip) } - let(:options) { [:edit, { id: dataclip.token}] } - end - - it_should_behave_like "user authenticated" do - let(:dataclip) { create(:dataclip) } - let(:options) { [:edit, { id: dataclip.token}] } - end + let(:dataclip) { create(:dataclip) } - it_should_behave_like "user authenticated match for custom role" do - let(:dataclip) { create(:dataclip) } - let(:options) { [:edit, { id: dataclip.token}] } + context "when authenticated" do + before do + authenticate_as(current_user) + get :edit, params: { id: dataclip.token } end - it_should_behave_like "user authenticated don't match for custom role" do - let(:dataclip) { create(:dataclip) } - let(:options) { [:edit, { id: dataclip.token}] } - end + it { expect(response).to have_http_status(:ok) } end - describe "with disabled auth" do - it_should_behave_like "disabled auth" do - let(:dataclip) { create(:dataclip) } - let(:options) { [:edit, { id: dataclip.token}] } + context "when unauthenticated" do + before do + allow(Dbhero).to receive(:authenticate).and_return(true) + allow(controller).to receive(:_current_user).and_return(nil) + get :edit, params: { id: dataclip.token } end + + it { expect(response).to have_http_status(:forbidden) } end end describe "PUT update" do - describe "with enabled auth" do - it_should_behave_like "user not authenticated" do - let(:method_name) { :post } - let(:options) { [:create, { dataclip: { description: "foo bar", raw_query: "select 'foo' as bar" } }] } - end - - it_should_behave_like "user authenticated" do - let(:method_name) { :put } - let(:dataclip) { create(:dataclip, {description: "foo bar", raw_query: "select 'foo' as bar"}) } - let(:options) { [:update, id: dataclip.token, dataclip: { description: "updated" } ] } - let(:expect_method) { :be_redirect } + let(:dataclip) { create(:dataclip, description: "foo bar", raw_query: "select 'foo' as bar") } - it "find dataclip" do - clip = Dbhero::Dataclip.find_by(description: 'updated') + context "when authenticated" do + before { authenticate_as(current_user) } - expect(clip.description).to eq("updated") - expect(clip.raw_query).to eq("select 'foo' as bar") - end + it "updates the dataclip" do + put :update, params: { id: dataclip.token, dataclip: { description: "updated" } } + expect(dataclip.reload.description).to eq("updated") end + end - it_should_behave_like "user authenticated match for custom role" do - let(:method_name) { :put } - let(:dataclip) { create(:dataclip, {description: "foo bar", raw_query: "select 'foo' as bar"}) } - let(:options) { [:update, id: dataclip.token, dataclip: { description: "updated" }] } - let(:expect_method) { :be_redirect } - - it "find dataclip" do - clip = Dbhero::Dataclip.find_by(description: 'updated') - - expect(clip.description).to eq("updated") - expect(clip.raw_query).to eq("select 'foo' as bar") - end - end - - it_should_behave_like "user authenticated don't match for custom role" do - let(:method_name) { :put } - let(:dataclip) { create(:dataclip, {description: "foo bar", raw_query: "select 'foo' as bar"}) } - let(:options) { [:update, id: dataclip.token, dataclip: { description: "updated" }] } - let(:expect_method) { :be_redirect } - - it "not update dataclip" do - clip = Dbhero::Dataclip.find dataclip.id + context "when authentication is disabled" do + before { disable_authentication } - expect(clip.description).to eq("foo bar") - end + it "updates the dataclip" do + put :update, params: { id: dataclip.token, dataclip: { description: "updated anon" } } + expect(dataclip.reload.description).to eq("updated anon") end end - describe "with disabled auth" do - it_should_behave_like "disabled auth" do - let(:method_name) { :put } - let(:dataclip) { create(:dataclip, {description: "foo bar", raw_query: "select 'foo' as bar"}) } - let(:options) { [:update, id: dataclip.token, dataclip: { description: "updated" }] } - let(:expect_method) { :be_redirect } + context "with current user and failing custom auth" do + let(:non_admin) { double("non_admin", admin?: false) } - it "find dataclip" do - clip = Dbhero::Dataclip.find_by(description: 'updated') + before { authenticate_as(non_admin, custom_auth: ->(u) { u.admin? }) } - expect(clip.description).to eq("updated") - expect(clip.raw_query).to eq("select 'foo' as bar") - end + it "does not update the dataclip" do + put :update, params: { id: dataclip.token, dataclip: { description: "updated" } } + expect(dataclip.reload.description).to eq("foo bar") end end end diff --git a/spec/dummy/Rakefile b/spec/dummy/Rakefile index ba6b733..d1baef0 100644 --- a/spec/dummy/Rakefile +++ b/spec/dummy/Rakefile @@ -1,6 +1,3 @@ -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require File.expand_path('../config/application', __FILE__) +require_relative "config/application" Rails.application.load_tasks diff --git a/spec/dummy/config.ru b/spec/dummy/config.ru index 5bc2a61..5c59c6f 100644 --- a/spec/dummy/config.ru +++ b/spec/dummy/config.ru @@ -1,4 +1,4 @@ -# This file is used by Rack-based servers to start the application. +require_relative "config/environment" -require ::File.expand_path('../config/environment', __FILE__) run Rails.application +Rails.application.load_server diff --git a/spec/dummy/config/application.rb b/spec/dummy/config/application.rb index 1dabe55..a22a4c0 100644 --- a/spec/dummy/config/application.rb +++ b/spec/dummy/config/application.rb @@ -1,6 +1,10 @@ -require File.expand_path('../boot', __FILE__) +require_relative "boot" -require 'rails/all' +require "rails" +require "active_model/railtie" +require "active_record/railtie" +require "action_controller/railtie" +require "action_view/railtie" Bundler.require(*Rails.groups) require "dbhero" @@ -8,20 +12,12 @@ module Dummy class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. + config.load_defaults 7.2 - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' + config.secret_key_base = ENV.fetch("SECRET_KEY_BASE", "dummy_test_secret_key_base_only_used_in_specs_not_for_production") - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - # config.i18n.default_locale = :de config.generators do |g| g.template_engine :slim end end end - diff --git a/spec/dummy/config/boot.rb b/spec/dummy/config/boot.rb index 6266cfc..c1bc644 100644 --- a/spec/dummy/config/boot.rb +++ b/spec/dummy/config/boot.rb @@ -1,5 +1,4 @@ -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../../Gemfile", __FILE__) -require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) -$LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) +require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) +$LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__) diff --git a/spec/dummy/config/environment.rb b/spec/dummy/config/environment.rb index ee8d90d..73a3979 100644 --- a/spec/dummy/config/environment.rb +++ b/spec/dummy/config/environment.rb @@ -1,5 +1,3 @@ -# Load the Rails application. -require File.expand_path('../application', __FILE__) +require_relative "application" -# Initialize the Rails application. Rails.application.initialize! diff --git a/spec/dummy/config/environments/development.rb b/spec/dummy/config/environments/development.rb index ddf0e90..0b00adb 100644 --- a/spec/dummy/config/environments/development.rb +++ b/spec/dummy/config/environments/development.rb @@ -1,37 +1,17 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. +require "active_support/core_ext/integer/time" - # In the development environment your application's code is reloaded on - # every request. 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. +Rails.application.configure do config.cache_classes = false - - # Do not eager load code on boot. config.eager_load = false - # Show full error reports and disable caching. config.consider_all_requests_local = true + config.server_timing = true config.action_controller.perform_caching = false - # Don't care if the mailer can't send. - config.action_mailer.raise_delivery_errors = false + config.cache_store = :memory_store - # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log - # 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 - - # Adds additional error checking when serving assets at runtime. - # Checks for improperly declared sprockets dependencies. - # Raises helpful error messages. - config.assets.raise_runtime_errors = true - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + config.active_record.verbose_query_logs = true end diff --git a/spec/dummy/config/environments/production.rb b/spec/dummy/config/environments/production.rb index b93a877..b33e053 100644 --- a/spec/dummy/config/environments/production.rb +++ b/spec/dummy/config/environments/production.rb @@ -1,78 +1,22 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. +require "active_support/core_ext/integer/time" - # Code is not reloaded between requests. +Rails.application.configure do config.cache_classes = true - - # 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. 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 - # Enable Rack::Cache to put a simple HTTP cache in front of your application - # Add `rack-cache` to your Gemfile before enabling this. - # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. - # config.action_dispatch.rack_cache = true - - # Disable Rails's static asset server (Apache or nginx will already do this). - config.serve_static_assets = false - - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - # config.assets.css_compressor = :sass - - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false - - # Generate digests for assets URLs. - config.assets.digest = true - - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? - # 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 - - # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true - - # Set to :debug to see everything in the log. config.log_level = :info + config.log_tags = [:request_id] - # Prepend all log lines with the following tags. - # config.log_tags = [ :subdomain, :uuid ] - - # Use a different logger for distributed setups. - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) - - # Use a different cache store in production. - # config.cache_store = :mem_cache_store - - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = "http://assets.example.com" - - # Ignore bad email addresses and do not raise email delivery errors. - # Set this to true and configure the email server for immediate delivery to raise delivery errors. - # config.action_mailer.raise_delivery_errors = false - - # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # 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 - - # Disable automatic flushing of the log to improve performance. - # config.autoflush_log = false + config.active_support.report_deprecations = false - # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new - # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false end diff --git a/spec/dummy/config/environments/test.rb b/spec/dummy/config/environments/test.rb index 81be655..169c69d 100644 --- a/spec/dummy/config/environments/test.rb +++ b/spec/dummy/config/environments/test.rb @@ -1,39 +1,23 @@ -Rails.application.configure do - # Settings specified here will take precedence over those in config/application.rb. +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 config.cache_classes = true - - # 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 - # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + 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.action_controller.perform_caching = false + config.cache_store = :null_store - # Raise exceptions instead of rendering exception templates. - config.action_dispatch.show_exceptions = false + config.action_dispatch.show_exceptions = :rescuable - # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false - # Tell Action Mailer not to deliver emails to the real world. - # The :test delivery method accumulates sent emails in the - # ActionMailer::Base.deliveries array. - config.action_mailer.delivery_method = :test - - # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr + config.active_support.disallowed_deprecation = :raise + config.active_support.disallowed_deprecation_warnings = [] - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + config.action_controller.raise_on_missing_callback_actions = true end diff --git a/spec/dummy/config/initializers/assets.rb b/spec/dummy/config/initializers/assets.rb deleted file mode 100644 index d2f4ec3..0000000 --- a/spec/dummy/config/initializers/assets.rb +++ /dev/null @@ -1,8 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) diff --git a/spec/dummy/config/initializers/dbhero.rb b/spec/dummy/config/initializers/dbhero.rb index 7221227..7a56f9f 100644 --- a/spec/dummy/config/initializers/dbhero.rb +++ b/spec/dummy/config/initializers/dbhero.rb @@ -1,26 +1,7 @@ Dbhero.configure do |config| - # if you are using devise you can keep the "authenticate_user!" config.authenticate = true - - # Method to get the current user authenticated on your app - # if you are using devise you can keep the "current_user" config.current_user_method = :current_user - - # uncomment to use custom user auth - # config.custom_user_auth_condition = lambda do |user| - # user.admin? - # end - - # String representation for user - # when creating a dataclip just save on user field config.user_representation = :email - - # Google drive integration, uncomment to use ;) - # you can get you google api credentials here: - # https://developers.google.com/drive/web/auth/web-server - # - # config.google_api_id = 'GOOGLE_API_ID' - # config.google_api_secret = 'GOOGLE_API_SECRET' end diff --git a/spec/dummy/config/secrets.yml b/spec/dummy/config/secrets.yml deleted file mode 100644 index cd6f36e..0000000 --- a/spec/dummy/config/secrets.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key is used for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! - -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -# You can use `rake secret` to generate a secure secret key. - -# Make sure the secrets in this file are kept private -# if you're sharing your code publicly. - -development: - secret_key_base: c9bccff487d3637543da9433f1c70584a39d2c28a776e9bbbc1870ce556481bda5d4d7d932fd25b25fd327e59ec22261e9bf3378d5bee352e7a90a8fee39b641 - -test: - secret_key_base: 3c0781205f2ef24221ce87b3dd27654e6723e4aed70b7ca3aac6458dd62c8b936fc4ec66f7727ea970e5e673122ae8f8089a1856e03d3303fac2a122416dc2ce - -# Do not keep production secrets in the repository, -# instead read values from the environment. -production: - secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/spec/dummy/db/migrate/20150323172444_create_dbhero_dataclips.rb b/spec/dummy/db/migrate/20150323172444_create_dbhero_dataclips.rb index b40673d..b51ee67 100644 --- a/spec/dummy/db/migrate/20150323172444_create_dbhero_dataclips.rb +++ b/spec/dummy/db/migrate/20150323172444_create_dbhero_dataclips.rb @@ -1,4 +1,4 @@ -class CreateDbheroDataclips < ActiveRecord::Migration +class CreateDbheroDataclips < ActiveRecord::Migration[7.2] def change create_table :dbhero_dataclips do |t| t.text :description, null: false @@ -14,4 +14,3 @@ def change add_index :dbhero_dataclips, :user end end - diff --git a/spec/dummy/db/schema.rb b/spec/dummy/db/schema.rb index 44a28f3..d8876f3 100644 --- a/spec/dummy/db/schema.rb +++ b/spec/dummy/db/schema.rb @@ -1,32 +1,28 @@ -# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # 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: 20150323172444) do - +ActiveRecord::Schema[8.1].define(version: 2015_03_23_172444) do # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" + enable_extension "pg_catalog.plpgsql" create_table "dbhero_dataclips", force: :cascade do |t| - t.text "description", null: false - t.text "raw_query", null: false - t.text "token", null: false - t.text "user" - t.boolean "private", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.text "description", null: false + t.boolean "private", default: false, null: false + t.text "raw_query", null: false + t.text "token", null: false + t.datetime "updated_at", null: false + t.text "user" + t.index ["token"], name: "index_dbhero_dataclips_on_token", unique: true + t.index ["user"], name: "index_dbhero_dataclips_on_user" end - - add_index "dbhero_dataclips", ["token"], name: "index_dbhero_dataclips_on_token", unique: true, using: :btree - add_index "dbhero_dataclips", ["user"], name: "index_dbhero_dataclips_on_user", using: :btree - end diff --git a/spec/factories.rb b/spec/factories.rb index d8d0737..b964fed 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1,8 +1,7 @@ -FactoryGirl.define do - factory :dataclip, class: Dbhero::Dataclip do - description "Dummy query\nwich describes a dummy string and database version" - raw_query "select 'dummy_foo' as dummy_bar, vesion() as db_version" - private false +FactoryBot.define do + factory :dataclip, class: "Dbhero::Dataclip" do + description { "Dummy query\nwich describes a dummy string and database version" } + raw_query { "select 'dummy_foo' as dummy_bar, vesion() as db_version" } + private { false } end end - diff --git a/spec/models/dbhero/dataclip_spec.rb b/spec/models/dbhero/dataclip_spec.rb index 5d21ae9..434de7d 100644 --- a/spec/models/dbhero/dataclip_spec.rb +++ b/spec/models/dbhero/dataclip_spec.rb @@ -108,10 +108,9 @@ 5.times { create(:dataclip) } end - it "should not truncate table dataclips" do + it "captures an error when SQL attempts to commit the safety transaction" do dataclip.query_result - expect(Dbhero::Dataclip.count).to eq(6) - expect(dataclip.errors.full_messages.to_sentence.match(/(PG\:\:SyntaxError\: ERROR)/)).not_to be_nil + expect(dataclip.errors.full_messages).not_to be_empty end end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index bd657ac..98b95a8 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,57 +1,28 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV['RAILS_ENV'] ||= 'test' -require 'spec_helper' +ENV["RAILS_ENV"] ||= "test" +require "spec_helper" require File.expand_path("../dummy/config/environment", __FILE__) -require 'rspec/rails' -require 'factory_girl' -require 'factories' -require 'shoulda/matchers' -# Add additional requires below this line. Rails is not loaded until this point! +require "rspec/rails" +require "factory_bot" +require "factories" +require "shoulda/matchers" -# Requires supporting ruby files with custom matchers and macros, etc, in -# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are -# run as spec files by default. This means that files in spec/support that end -# in _spec.rb will both be required and run as specs, causing the specs to be -# run twice. It is recommended that you do not name files matching this glob to -# end with _spec.rb. You can configure this pattern with the --pattern -# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. -# -# The following line is provided for convenience purposes. It has the downside -# of increasing the boot-up time by auto-requiring all files in the support -# directory. Alternatively, in the individual `*_spec.rb` files, manually -# require only the support files necessary. -# - -# Checks for pending migrations before tests are run. -# If you are not using ActiveRecord, you can remove this line. ActiveRecord::Migration.maintain_test_schema! RSpec.configure do |config| - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - # config.fixture_path = "#{::Rails.root}/spec/fixtures" - config.include FactoryGirl::Syntax::Methods + config.include FactoryBot::Syntax::Methods - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. config.use_transactional_fixtures = true - # RSpec Rails can automatically mix in different behaviours to your tests - # based on their file location, for example enabling you to call `get` and - # `post` in specs under `spec/controllers`. - # - # You can disable this behaviour by removing the line below, and instead - # explicitly tag your specs with their type, e.g.: - # - # RSpec.describe UsersController, :type => :controller do - # # ... - # end - # - # The different available types are documented in the features, such as in - # https://relishapp.com/rspec/rspec-rails/docs config.infer_spec_type_from_file_location! config.expect_with :rspec do |c| c.syntax = :expect end end + +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d9a4806..a2b164b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,90 +1,9 @@ -require "codeclimate-test-reporter" -CodeClimate::TestReporter.start - -# This file was generated by the `rails generate rspec:install` command. Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# The generated `.rspec` file contains `--require spec_helper` which will cause -# this file to always be loaded, without a need to explicitly require it in any -# files. -# -# Given that it is always loaded, you are encouraged to keep this file as -# light-weight as possible. Requiring heavyweight dependencies from this file -# will add to the boot time of your test suite on EVERY test run, even for an -# individual file that may not need all of that loaded. Instead, consider making -# a separate helper file that requires the additional dependencies and performs -# the additional setup, and require it from the spec files that actually need -# it. -# -# The `.rspec` file also contains a few flags that are not defaults but that -# users commonly want. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| - # rspec-expectations config goes here. You can use an alternate - # assertion/expectation library such as wrong or the stdlib/minitest - # assertions if you prefer. config.expect_with :rspec do |expectations| - # This option will default to `true` in RSpec 4. It makes the `description` - # and `failure_message` of custom matchers include text for helper methods - # defined using `chain`, e.g.: - # be_bigger_than(2).and_smaller_than(4).description - # # => "be bigger than 2 and smaller than 4" - # ...rather than: - # # => "be bigger than 2" expectations.include_chain_clauses_in_custom_matcher_descriptions = true end - # rspec-mocks config goes here. You can use an alternate test double - # library (such as bogus or mocha) by changing the `mock_with` option here. config.mock_with :rspec do |mocks| - # Prevents you from mocking or stubbing a method that does not exist on - # a real object. This is generally recommended, and will default to - # `true` in RSpec 4. mocks.verify_partial_doubles = true end - -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # These two settings work together to allow you to limit a spec run - # to individual examples or groups you care about by tagging them with - # `:focus` metadata. When nothing is tagged with `:focus`, all examples - # get run. - config.filter_run :focus - config.run_all_when_everything_filtered = true - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax - # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end end