diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10708a84..50094ff0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.2.10 + ruby-version: 4.0.1 - uses: actions/cache@v4 with: path: vendor/bundle diff --git a/.rubocop.yml b/.rubocop.yml index f04e59f0..c16d38cb 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,11 +1,11 @@ -require: +plugins: - rubocop-packaging - rubocop-performance - rubocop-rails - rubocop-rspec AllCops: - TargetRubyVersion: 3.1 + TargetRubyVersion: 4.0 # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop # to ignore them, so only the ones explicitly set in this file are enabled. DisabledByDefault: true diff --git a/.ruby-version b/.ruby-version index f15386a5..90cdbdcb 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.10 +ruby-4.0.1 diff --git a/Dockerfile b/Dockerfile index 38c6b2b0..80c7317c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM phusion/passenger-full:3.1.6 +FROM phusion/passenger-ruby40:3.1.6 LABEL maintainer="support@datacite.org" # Set correct environment variables @@ -10,8 +10,8 @@ RUN usermod -a -G docker_env app # Use baseimage-docker's init process CMD ["/sbin/my_init"] -# Use Ruby 3.2.10 -RUN bash -lc 'rvm --default use ruby-3.2.10' +# set ddefault Ruby version +RUN bash -lc 'rvm --default use ruby-4.0.1' # Set debconf to run non-interactively RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections diff --git a/Gemfile b/Gemfile index 0ac5bb1d..bc8a3ae6 100755 --- a/Gemfile +++ b/Gemfile @@ -1,122 +1,99 @@ source "https://rubygems.org" -gem "bootsnap", "~> 1.4", ">= 1.4.4", require: false -gem "msgpack", "~> 1.4.4" -gem "mysql2", "~> 0.5.0" -gem "rails", "~> 7.2", ">= 7.2.3" +gem "bootsnap", "~> 1.23", require: false +gem "msgpack", "~> 1.8" +gem "mysql2", "~> 0.5.7" +gem "rails", "~> 8.1", ">= 8.1.2" -gem "aasm", "~> 5.0", ">= 5.0.6" -gem "active_model_serializers", "~> 0.10.10" -gem "addressable", "~> 2.7" -gem "aws-sdk-s3", require: false -gem "aws-sdk-sqs", "~> 1.23", ">= 1.23.1" -gem "base32-crockford-checksum", "~> 0.2.3" -gem "config", "~> 5.4" -gem "connection_pool", "< 3.0" -gem "dotenv", "~> 2.7", ">= 2.7.5" +gem "aasm", "~> 5.5", ">= 5.5.2" +gem "active_model_serializers", "~> 0.10.16" +gem "addressable", "~> 2.8", ">= 2.8.9" +gem "aws-sdk-s3", "~> 1.215", require: false +gem "aws-sdk-sqs", "~> 1.111" +gem "config", "~> 5.6", ">= 5.6.1" +gem "connection_pool", "~> 3.0", ">= 3.0.2" +gem "dotenv", "~> 3.2" # IMPORTANT!!! # We have monkey patched this gem -> config/initializers/serialization_core.rb # Please check this before upgrading/downgrading versions gem "jsonapi-serializer", "~> 2.2" -gem "flipper", "~> 1.3" -gem "flipper-active_support_cache_store" -gem "flipper-api" -gem "flipper-redis" -gem "flipper-ui" -gem "nilify_blanks", "~> 1.3" -gem "oj", ">= 2.8.3" -gem "oj_mimic_json", "~> 1.0", ">= 1.0.1" -gem "orcid_client", "~> 0.17.1" -gem "postrank-uri", "~> 1.1" -gem "rake", "~> 12.0" -gem "sentry-raven", "~> 3.1", ">= 3.1.2" -gem "shoryuken", "~> 7.0" +gem "flipper", "~> 1.4" +gem "flipper-active_support_cache_store", "~> 1.4" +gem "flipper-redis", "~> 1.4" +gem "flipper-ui", "~> 1.4" +gem "oj", "~> 3.16", ">= 3.16.16" +gem "orcid_client", "~> 0.18.0" +gem "rake", "~> 13.3", ">= 13.3.1" +gem "sentry-ruby", "~> 6.4", ">= 6.4.1" +gem "sentry-rails", "~> 6.4", ">= 6.4.1" +gem "shoryuken", "~> 7.0", ">= 7.0.1" gem "strip_attributes", "~> 1.9", ">= 1.9.2" -gem "tzinfo-data", "~> 1.2019", ">= 1.2019.3" +gem "tzinfo-data", "~> 1.2026", ">= 1.2026.1" -gem "commonmarker", "~> 0.21.0" -gem "country_select", "~> 4.0" -gem "dalli", "~> 2.7", ">= 2.7.10" -gem "hashie" -gem "kaminari", "~> 1.2" -gem "lograge", "~> 0.11.2" +gem "dalli", "~> 5.0", ">= 5.0.2" +gem "hashie", "~> 5.1" +gem "kaminari", "~> 1.2", ">= 1.2.2" +gem "lograge", "~> 0.14.0" gem "logstash-event", "~> 1.2", ">= 1.2.02" gem "logstash-logger", "~> 0.26.1" -gem "namae", "~> 1.0", ">= 1.0.1" -gem "nokogiri", "~> 1.10", ">= 1.10.7" -gem "rack-cors", "~> 1.0", require: "rack/cors" -gem "rouge", "~> 3.15" -gem "simple_form", "~> 4.1.0" -gem "cancancan", "~> 3.0" -gem "devise", "~> 4.8", ">= 4.8.1" -gem "gravtastic", "~> 3.2", ">= 3.2.6" -gem "jwt", "~> 2.2", ">= 2.2.1" -gem "mailgun-ruby", "~> 1.2" -gem "oauth2", "~> 1.4" -gem "omniauth", "~> 2.0", ">= 2.0.4" +gem "namae", "~> 1.2" +gem "nokogiri", "~> 1.19", ">= 1.19.1" +gem "simple_form", "~> 5.4", ">= 5.4.1" + +gem "cancancan", "~> 3.6", ">= 3.6.1" +gem "devise", "~> 5.0", ">= 5.0.2" +gem "jwt", "~> 3.1", ">= 3.1.2" +gem "mailgun-ruby", "~> 1.4", ">= 1.4.2" # not sure this is used +gem "omniauth", "~> 2.1", ">= 2.1.4" gem "omniauth-github", "~> 2.0" -gem "omniauth-globus", "~> 0.9.1" gem "omniauth-orcid", "~> 2.0" -gem "omniauth-rails_csrf_protection", "~> 1.0" -gem "repost", "~> 0.3.7" -gem "validates_email_format_of", "~> 1.6", ">= 1.6.3" +gem "omniauth-rails_csrf_protection", "~> 2.0", ">= 2.0.1" +gem "repost", "~> 0.5.1" -gem "apollo-federation", "~> 1.0" -gem "batch-loader", "~> 1.4", ">= 1.4.1" -gem "elasticsearch", "~> 7.1.0" -gem "elasticsearch-model", "~> 7.0", require: "elasticsearch/model" -gem "elasticsearch-rails", "~> 7.0" +gem "apollo-federation", "~> 3.10", ">= 3.10.3" +gem "elasticsearch", "~> 8.19", ">= 8.19.3" +gem "elasticsearch-model", "~> 8.0", ">= 8.0.1", require: "elasticsearch/model" +gem "elasticsearch-rails", "~> 8.0", ">= 8.0.1" +gem "elastic-transport", "~> 8.0", ">= 8.0.1" gem "faraday_middleware-aws-sigv4", "~> 0.3.0" -gem "google-protobuf", "3.19.6" -gem "graphql", "~> 2.0.0" -gem "graphql-batch", "~> 0.5.1" -gem "maremma", "~> 5.0" -gem "rack-utf8_sanitizer", "~> 1.6" +gem "google-protobuf", "4.34" +gem "graphql", "~> 2.5", ">= 2.5.21" +gem "graphql-batch", "~> 0.6.1" +gem "maremma", "~> 6.0" -gem "coffee-rails", "~> 4.1", ">= 4.1.1" -gem "git", "~> 1.5" -gem "mini_magick", "~> 4.5", ">= 4.5.1" -gem "rack-jwt" -gem "remotipart", "~> 1.2" -gem "sprockets", "~> 3.7", ">= 3.7.2" -gem "sprockets-rails", "~> 3.2", ">= 3.2.1", require: "sprockets/railtie" -gem "uglifier", "~> 2.7", ">= 2.7.2" +gem "mini_magick", "~> 5.3", ">= 5.3.1" +gem "sprockets", "~> 4.2", ">= 4.2.2" +gem "sprockets-rails", "~> 3.5", ">= 3.5.2", require: "sprockets/railtie" group :development, :test do - gem "better_errors" - gem "binding_of_caller" - gem "byebug", platforms: %i[mri mingw x64_mingw] - gem "rspec-benchmark", "~> 0.4.0" - gem "rspec-graphql_matchers", "2.0.0.pre.rc.0" - gem "rspec-rails", "~> 6.1", ">= 6.1.1" - gem "rubocop", "~> 1.3", ">= 1.3.1" - gem "rubocop-performance", "~> 1.5", ">= 1.5.1" - gem "rubocop-rails", "~> 2.8", ">= 2.8.1" - gem "rubocop-packaging", "~> 0.5.1" - gem "rubocop-rspec", "~> 2.0", require: false + gem "better_errors", "~> 2.10", ">= 2.10.1" + gem "binding_of_caller", "~> 2.0" + gem "byebug", "~> 13.0", platforms: %i[mri mingw x64_mingw] + gem "rspec-rails", "~> 8.0", ">= 8.0.4" + gem "rubocop", "~> 1.85", ">= 1.85.1" + gem "rubocop-performance", "~> 1.26", ">= 1.26.1" + gem "rubocop-rails", "~> 2.34", ">= 2.34.3" + gem "rubocop-packaging", "~> 0.6.0" + gem "rubocop-rspec", "~> 3.9", require: false end group :development do - gem "listen", "~> 3.9" - gem "spring" - gem "spring-commands-rspec" + gem "listen", "~> 3.10" + gem "spring", "~> 4.4", ">= 4.4.2" gem "spring-watcher-listen", "~> 2.1" end group :test do - gem "capybara", "~> 3.31" - gem "capybara-screenshot", "~> 1.0", ">= 1.0.24" - gem "cuprite", "~> 0.9" + gem "capybara", "~> 3.40" + gem "capybara-screenshot", "~> 1.0", ">= 1.0.27" + gem "cuprite", "~> 0.17" gem "database_cleaner-active_record", "~> 2.2", ">= 2.2.2" - gem "elasticsearch-extensions", "~> 0.0.29" gem "email_spec", "~> 2.2" - gem "factory_bot_rails", "~> 4.8", ">= 4.8.2" - gem "hashdiff", [">= 1.0.0.beta1", "< 2.0.0"] - gem "shoulda-matchers", "~> 4.1", ">= 4.1.2" + gem "factory_bot_rails", "~> 6.5", ">= 6.5.1" + gem "shoulda-matchers", "~> 7.0", ">= 7.0.1" gem "simplecov", "~> 0.22.0" - gem "test-prof", "~> 0.10.2" - gem "vcr", "~> 6.1" - gem "webmock", "~> 3.1" - gem "with_env", "~> 1.1" + gem "test-prof", "~> 1.5", ">= 1.5.2" + gem "vcr", "~> 6.4" + gem "webmock", "~> 3.26", ">= 3.26.1" end diff --git a/Gemfile.lock b/Gemfile.lock index 628af92e..268d12a6 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,96 +1,96 @@ GEM remote: https://rubygems.org/ specs: - aasm (5.2.0) + aasm (5.5.2) concurrent-ruby (~> 1.0) - actioncable (7.2.3) - actionpack (= 7.2.3) - activesupport (= 7.2.3) + action_text-trix (2.1.16) + railties + actioncable (8.1.2) + actionpack (= 8.1.2) + activesupport (= 8.1.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.2.3) - actionpack (= 7.2.3) - activejob (= 7.2.3) - activerecord (= 7.2.3) - activestorage (= 7.2.3) - activesupport (= 7.2.3) + actionmailbox (8.1.2) + actionpack (= 8.1.2) + activejob (= 8.1.2) + activerecord (= 8.1.2) + activestorage (= 8.1.2) + activesupport (= 8.1.2) mail (>= 2.8.0) - actionmailer (7.2.3) - actionpack (= 7.2.3) - actionview (= 7.2.3) - activejob (= 7.2.3) - activesupport (= 7.2.3) + actionmailer (8.1.2) + actionpack (= 8.1.2) + actionview (= 8.1.2) + activejob (= 8.1.2) + activesupport (= 8.1.2) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.2.3) - actionview (= 7.2.3) - activesupport (= 7.2.3) - cgi + actionpack (8.1.2) + actionview (= 8.1.2) + activesupport (= 8.1.2) nokogiri (>= 1.8.5) - racc - rack (>= 2.2.4, < 3.3) + rack (>= 2.2.4) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (7.2.3) - actionpack (= 7.2.3) - activerecord (= 7.2.3) - activestorage (= 7.2.3) - activesupport (= 7.2.3) + actiontext (8.1.2) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.2) + activerecord (= 8.1.2) + activestorage (= 8.1.2) + activesupport (= 8.1.2) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.2.3) - activesupport (= 7.2.3) + actionview (8.1.2) + activesupport (= 8.1.2) builder (~> 3.1) - cgi erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - active_model_serializers (0.10.14) + active_model_serializers (0.10.16) actionpack (>= 4.1) activemodel (>= 4.1) case_transform (>= 0.2) jsonapi-renderer (>= 0.1.1.beta1, < 0.3) - activejob (7.2.3) - activesupport (= 7.2.3) + activejob (8.1.2) + activesupport (= 8.1.2) globalid (>= 0.3.6) - activemodel (7.2.3) - activesupport (= 7.2.3) - activerecord (7.2.3) - activemodel (= 7.2.3) - activesupport (= 7.2.3) + activemodel (8.1.2) + activesupport (= 8.1.2) + activerecord (8.1.2) + activemodel (= 8.1.2) + activesupport (= 8.1.2) timeout (>= 0.4.0) - activestorage (7.2.3) - actionpack (= 7.2.3) - activejob (= 7.2.3) - activerecord (= 7.2.3) - activesupport (= 7.2.3) + activestorage (8.1.2) + actionpack (= 8.1.2) + activejob (= 8.1.2) + activerecord (= 8.1.2) + activesupport (= 8.1.2) marcel (~> 1.0) - activesupport (7.2.3) + activesupport (8.1.2) base64 - benchmark (>= 0.3) 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) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - ansi (1.5.0) - apollo-federation (1.1.5) - google-protobuf (~> 3.7) - graphql (>= 1.9.8) + uri (>= 0.13.1) + addressable (2.8.9) + public_suffix (>= 2.0.2, < 8.0) + apollo-federation (3.10.3) + google-protobuf (< 5) + graphql ast (2.4.2) aws-eventstream (1.4.0) aws-partitions (1.1206.0) - aws-sdk-core (3.241.4) + aws-sdk-core (3.243.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -101,244 +101,229 @@ GEM aws-sdk-kms (1.48.0) aws-sdk-core (~> 3, >= 3.120.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.103.0) - aws-sdk-core (~> 3, >= 3.120.0) + aws-sdk-s3 (1.215.0) + aws-sdk-core (~> 3, >= 3.243.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.4) - aws-sdk-sqs (1.110.0) + aws-sigv4 (~> 1.5) + aws-sdk-sqs (1.111.0) aws-sdk-core (~> 3, >= 3.241.4) aws-sigv4 (~> 1.5) aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) - base32-crockford-checksum (0.2.3) base64 (0.3.0) - batch-loader (1.5.0) bcp47_spec (0.2.1) bcrypt (3.1.20) - benchmark (0.5.0) - benchmark-perf (0.4.0) - benchmark-trend (0.2.0) - benchmark_methods (0.7) - better_errors (2.9.1) - coderay (>= 1.0.0) + better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) - bibtex-ruby (6.1.0) + rouge (>= 1.0.0) + bibtex-ruby (6.2.0) latex-decode (~> 0.0) + logger (~> 1.7) racc (~> 1.7) bigdecimal (3.3.1) - binding_of_caller (1.0.0) - debug_inspector (>= 0.0.1) - bolognese (2.5.1) - activesupport (= 7.2.3) - benchmark_methods (~> 0.7) - bibtex-ruby (>= 5.1.0) - builder (~> 3.2, >= 3.2.2) - citeproc-ruby (~> 1.1, >= 1.1.12) - colorize (~> 0.8.1) - concurrent-ruby (~> 1.1, >= 1.1.5) - csl-styles (~> 1.0, >= 1.0.1.10) - edtf (~> 3.0, >= 3.0.4) - gender_detector (~> 0.1.2) - iso8601 (~> 0.9.1) - json-ld-preloaded (~> 3.1, >= 3.1.3) - jsonlint (~> 0.3.0) - loofah (~> 2.0, >= 2.0.3) - maremma (~> 5.0) - namae (~> 1.0) - nokogiri (~> 1.16, >= 1.16.2) - oj (~> 3.10) - oj_mimic_json (~> 1.0, >= 1.0.1) - postrank-uri (~> 1.0, >= 1.0.18) - rdf-rdfxml (~> 3.1) - rdf-turtle (~> 3.1) - thor (>= 0.19) - bootsnap (1.9.1) - msgpack (~> 1.0) + binding_of_caller (2.0.0) + debug_inspector (>= 1.2.0) + bolognese (2.6.0) + activesupport (~> 8.1, >= 8.1.2) + bibtex-ruby (~> 6.2) + builder (~> 3.3) + citeproc-ruby (~> 2.1, >= 2.1.8) + concurrent-ruby (~> 1.3, >= 1.3.6) + csl-styles (~> 2.0, >= 2.0.2) + csv (~> 3.3, >= 3.3.5) + edtf (~> 3.2) + gender_detector (~> 2.1) + iso8601 (~> 0.13.0) + json-ld-preloaded (~> 3.3, >= 3.3.2) + jsonlint (~> 0.4.0) + loofah (~> 2.25) + maremma (~> 6.0) + namae (~> 1.2) + nokogiri (~> 1.19, >= 1.19.1) + oj (~> 3.16, >= 3.16.15) + rdf-rdfxml (~> 3.3) + rdf-turtle (~> 3.3, >= 3.3.1) + thor (~> 1.5) + bootsnap (1.23.0) + msgpack (~> 1.2) builder (3.3.0) - byebug (11.1.3) - cancancan (3.5.0) - capybara (3.35.3) + byebug (13.0.0) + reline (>= 0.6.0) + cancancan (3.6.1) + capybara (3.40.0) addressable + matrix mini_mime (>= 0.1.3) - nokogiri (~> 1.8) + nokogiri (~> 1.11) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - capybara-screenshot (1.0.25) + capybara-screenshot (1.0.27) capybara (>= 1.0, < 4) launchy case_transform (0.2) activesupport - cgi (0.5.1) - citeproc (1.0.10) + citeproc (1.1.0) + date + forwardable + json namae (~> 1.0) - citeproc-ruby (1.1.14) + observer (< 1.0) + open-uri (< 1.0) + citeproc-ruby (2.1.8) citeproc (~> 1.0, >= 1.0.9) - csl (~> 1.6) - cliver (0.3.2) - coderay (1.1.3) - coffee-rails (4.2.2) - coffee-script (>= 2.2.0) - railties (>= 4.0.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.12.2) - colorize (0.8.1) - commonmarker (0.21.2) - ruby-enum (~> 0.5) + csl (~> 2.0) + observer (< 1.0) concurrent-ruby (1.3.6) - config (5.4.0) + config (5.6.1) deep_merge (~> 1.2, >= 1.2.1) - connection_pool (2.5.5) - countries (3.1.0) - i18n_data (~> 0.11.0) - sixarm_ruby_unaccent (~> 1.1) - unicode_utils (~> 1.4) - country_select (4.0.0) - countries (~> 3.0) - sort_alphabetical (~> 1.0) + ostruct + connection_pool (3.0.2) crack (0.4.5) rexml crass (1.0.6) - csl (1.6.0) - namae (~> 1.0) - rexml - csl-styles (1.0.1.11) - csl (~> 1.0) - cuprite (0.13) - capybara (>= 2.1, < 4) - ferrum (~> 0.11.0) - dalli (2.7.11) + csl (2.2.1) + forwardable (~> 1.3) + namae (~> 1.2) + open-uri (< 1.0) + rexml (~> 3.0) + set (~> 1.1) + singleton (< 1.0) + time (< 1.0) + csl-styles (2.0.2) + csl (~> 2.0) + csv (3.3.5) + cuprite (0.17) + capybara (~> 3.0) + ferrum (~> 0.17.0) + dalli (5.0.2) + logger database_cleaner-active_record (2.2.2) activerecord (>= 5.a) database_cleaner-core (~> 2.0) database_cleaner-core (2.0.1) date (3.5.1) - debug_inspector (1.1.0) + debug_inspector (1.2.0) deep_merge (1.2.2) - devise (4.9.4) + devise (5.0.2) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0) + railties (>= 7.0) responders warden (~> 1.2.3) diff-lcs (1.4.4) docile (1.4.0) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.6) + dotenv (3.2.0) drb (2.2.3) - ebnf (2.5.0) + ebnf (2.6.0) + base64 (~> 0.2) htmlentities (~> 4.3) rdf (~> 3.3) scanf (~> 1.0) sxp (~> 2.0) unicode-types (~> 1.8) - edtf (3.1.1) - activesupport (>= 3.0, < 8.0) - elasticsearch (7.1.0) - elasticsearch-api (= 7.1.0) - elasticsearch-transport (= 7.1.0) - elasticsearch-api (7.1.0) + edtf (3.2.0) + activesupport (>= 3.0, < 9.0) + elastic-transport (8.4.1) + faraday (< 3) multi_json - elasticsearch-extensions (0.0.33) - ansi - elasticsearch - elasticsearch-model (7.2.0) + elasticsearch (8.19.3) + elastic-transport (~> 8.3) + elasticsearch-api (= 8.19.3) + ostruct + elasticsearch-api (8.19.3) + multi_json + elasticsearch-model (8.0.1) activesupport (> 3) - elasticsearch (~> 7) + elasticsearch (~> 8) hashie - elasticsearch-rails (7.2.0) - elasticsearch-transport (7.1.0) - faraday - multi_json + elasticsearch-rails (8.0.1) email_spec (2.2.0) htmlentities (~> 4.3.3) launchy (~> 2.1) mail (~> 2.7) - erb (6.0.1) + erb (6.0.2) erubi (1.13.1) - excon (0.71.1) - execjs (2.8.1) - factory_bot (4.11.1) - activesupport (>= 3.0.0) - factory_bot_rails (4.11.1) - factory_bot (~> 4.11.1) - railties (>= 3.0.0) - faraday (2.9.0) - faraday-net_http (>= 2.0, < 3.2) - faraday-encoding (0.0.5) + excon (1.4.0) + logger + factory_bot (6.5.6) + activesupport (>= 6.1.0) + factory_bot_rails (6.5.1) + factory_bot (~> 6.5) + railties (>= 6.1.0) + faraday (2.14.1) + faraday-net_http (>= 2.0, < 3.5) + json + logger + faraday-encoding (0.0.6) faraday - faraday-excon (2.1.0) - excon (>= 0.27.4) - faraday (~> 2.0) - faraday-follow_redirects (0.3.0) + faraday-excon (2.4.0) + excon (>= 1.0.0) + faraday (>= 2.11.0, < 3) + faraday-follow_redirects (0.5.0) faraday (>= 1, < 3) - faraday-gzip (0.1.0) - faraday (>= 1.0) - zlib (~> 2.1) - faraday-multipart (1.0.4) - multipart-post (~> 2) + faraday-gzip (3.1.0) + faraday (>= 2.0, < 3) + zlib (~> 3.0) + faraday-multipart (1.2.0) + multipart-post (~> 2.0) faraday-net_http (3.1.0) net-http faraday_middleware-aws-sigv4 (0.3.0) aws-sigv4 (~> 1.0) faraday (>= 0.15) - ferrum (0.11) + ferrum (0.17.1) addressable (~> 2.5) - cliver (~> 0.3) + base64 (~> 0.2) concurrent-ruby (~> 1.1) - websocket-driver (>= 0.6, < 0.8) + webrick (~> 1.7) + websocket-driver (~> 0.7) ffi (1.16.3) - flipper (1.3.0) + fiber-storage (1.0.1) + flipper (1.4.0) concurrent-ruby (< 2) - flipper-active_support_cache_store (1.3.0) - activesupport (>= 4.2, < 8) - flipper (~> 1.3.0) - flipper-api (1.3.0) - flipper (~> 1.3.0) - rack (>= 1.4, < 4) - flipper-redis (1.3.0) - flipper (~> 1.3.0) + flipper-active_support_cache_store (1.4.0) + activesupport (>= 4.2, < 9) + flipper (~> 1.4.0) + flipper-redis (1.4.0) + flipper (~> 1.4.0) redis (>= 3.0, < 6) - flipper-ui (1.3.0) + flipper-ui (1.4.0) erubi (>= 1.0.0, < 2.0.0) - flipper (~> 1.3.0) + flipper (~> 1.4.0) rack (>= 1.4, < 4) rack-protection (>= 1.5.3, < 5.0.0) rack-session (>= 1.0.2, < 3.0.0) - sanitize (< 7) - gender_detector (0.1.2) - unicode_utils (>= 1.3.0) - git (1.9.1) - rchardet (~> 1.8) + sanitize (< 8) + forwardable (1.4.0) + gender_detector (2.1.0) globalid (1.3.0) activesupport (>= 6.1) - google-protobuf (3.19.6) - graphql (2.0.32) + google-protobuf (4.34.0) + bigdecimal + rake (~> 13.3) + graphql (2.5.21) base64 - graphql-batch (0.5.4) - graphql (>= 1.12.18, < 3) + fiber-storage + logger + graphql-batch (0.6.1) + graphql (>= 1.13, < 3) promise.rb (~> 0.7.2) - gravtastic (3.2.6) hashdiff (1.0.1) - hashie (4.1.0) + hashie (5.1.0) + logger htmlentities (4.3.4) - http-accept (1.7.0) - http-cookie (1.0.4) - domain_name (~> 0.5) - i18n (1.14.7) + i18n (1.14.8) concurrent-ruby (~> 1.0) - i18n_data (0.11.0) io-console (0.8.2) - irb (1.16.0) + irb (1.17.0) pp (>= 0.6.0) + prism (>= 1.3.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - iso8601 (0.9.1) + iso8601 (0.13.0) jmespath (1.6.2) json (2.5.1) json-canonicalization (1.0.0) @@ -350,37 +335,44 @@ GEM rack (>= 2.2, < 4) rdf (~> 3.3) rexml (~> 3.2) - json-ld-preloaded (3.3.1) + json-ld-preloaded (3.3.2) json-ld (~> 3.3) rdf (~> 3.3) + json-schema (6.2.0) + addressable (~> 2.8) + bigdecimal (>= 3.1, < 5) jsonapi-renderer (0.2.2) jsonapi-serializer (2.2.0) activesupport (>= 4.2) - jsonlint (0.3.0) + jsonlint (0.4.0) oj (~> 3) optimist (~> 3) - jwt (2.2.3) - kaminari (1.2.1) + jwt (3.1.2) + base64 + kaminari (1.2.2) activesupport (>= 4.1.0) - kaminari-actionview (= 1.2.1) - kaminari-activerecord (= 1.2.1) - kaminari-core (= 1.2.1) - kaminari-actionview (1.2.1) + kaminari-actionview (= 1.2.2) + kaminari-activerecord (= 1.2.2) + kaminari-core (= 1.2.2) + kaminari-actionview (1.2.2) actionview - kaminari-core (= 1.2.1) - kaminari-activerecord (1.2.1) + kaminari-core (= 1.2.2) + kaminari-activerecord (1.2.2) activerecord - kaminari-core (= 1.2.1) - kaminari-core (1.2.1) - latex-decode (0.4.0) + kaminari-core (= 1.2.2) + kaminari-core (1.2.2) + language_server-protocol (3.17.0.5) + latex-decode (0.4.2) launchy (2.5.0) addressable (~> 2.7) link_header (0.0.8) - listen (3.9.0) + lint_roller (1.1.0) + listen (3.10.0) + logger rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) logger (1.7.0) - lograge (0.11.2) + lograge (0.14.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) @@ -397,41 +389,47 @@ GEM net-imap net-pop net-smtp - mailgun-ruby (1.2.5) - rest-client (>= 2.0.2) + mailgun-ruby (1.4.2) + faraday (~> 2.1) + faraday-multipart (< 2) + mini_mime + zeitwerk marcel (1.1.0) - maremma (5.0.0) - activesupport (>= 4.2.5) - addressable (>= 2.3.6) + maremma (6.0.0) + activesupport (~> 8.1, >= 8.1.2) + addressable (~> 2.8, >= 2.8.9) builder (~> 3.2, >= 3.2.2) - excon (~> 0.71.0) + excon (~> 1.3, >= 1.3.2) faraday (>= 2.0) - faraday-encoding (~> 0.0.5) - faraday-excon (~> 2.1.0) - faraday-follow_redirects (~> 0.3.0) - faraday-gzip (~> 0.1.0) - faraday-multipart (~> 1.0.4) - nokogiri (~> 1.16, >= 1.16.2) - oj (>= 2.8.3) + faraday-encoding (~> 0.0.6) + faraday-excon (~> 2.4.0) + faraday-follow_redirects (~> 0.5.0) + faraday-gzip (~> 3.1.0) + faraday-multipart (~> 1.2.0) + nokogiri (~> 1.19, >= 1.19.1) + oj (~> 3.16, >= 3.16.15) oj_mimic_json (~> 1.0, >= 1.0.1) - matrix (0.4.2) - mime-types (3.3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2021.0901) - mini_magick (4.11.0) + matrix (0.4.3) + mcp (0.8.0) + json-schema (>= 4.1) + mini_magick (5.3.1) + logger mini_mime (1.1.5) mini_portile2 (2.8.9) - minitest (6.0.0) + minitest (6.0.2) + drb (~> 2.0) prism (~> 1.5) - msgpack (1.4.5) + msgpack (1.8.0) multi_json (1.15.0) multi_xml (0.6.0) multipart-post (2.1.1) - mysql2 (0.5.6) - namae (1.0.2) + mysql2 (0.5.7) + bigdecimal + namae (1.2.0) + racc (~> 1.7) net-http (0.4.1) uri - net-imap (0.6.2) + net-imap (0.6.3) date net-protocol net-pop (0.1.2) @@ -440,111 +438,103 @@ GEM timeout net-smtp (0.5.1) net-protocol - netrc (0.11.0) - nilify_blanks (1.4.0) - activerecord (>= 4.0.0) - activesupport (>= 4.0.0) nio4r (2.7.5) - nokogiri (1.18.10) + nokogiri (1.19.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) - oauth2 (1.4.11) - faraday (>= 0.17.3, < 3.0) - jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) + oauth2 (2.0.18) + faraday (>= 0.17.3, < 4.0) + jwt (>= 1.0, < 4.0) + logger (~> 1.2) multi_xml (~> 0.5) rack (>= 1.2, < 4) - oj (3.13.9) + snaky_hash (~> 2.0, >= 2.0.3) + version_gem (~> 1.1, >= 1.1.9) + observer (0.1.2) + oj (3.16.16) + bigdecimal (>= 3.0) + ostruct (>= 0.2) oj_mimic_json (1.0.1) - omniauth (2.0.4) + omniauth (2.1.4) hashie (>= 3.4.6) - rack (>= 1.6.2, < 3) + logger + rack (>= 2.2.3) rack-protection omniauth-github (2.0.0) omniauth (~> 2.0) omniauth-oauth2 (~> 1.7.1) - omniauth-globus (0.9.1) - jwt (~> 2.0) - omniauth (>= 1.9) - omniauth-oauth2 (~> 1.6) - omniauth-oauth2 (1.7.1) - oauth2 (~> 1.4) + omniauth-oauth2 (1.7.3) + oauth2 (>= 1.4, < 3) omniauth (>= 1.9, < 3) omniauth-orcid (2.1.1) omniauth-oauth2 (~> 1.3) ruby_dig (~> 0.0.2) - omniauth-rails_csrf_protection (1.0.0) + omniauth-rails_csrf_protection (2.0.1) actionpack (>= 4.2) omniauth (~> 2.0) - optimist (3.2.0) - orcid_client (0.17.1) - activesupport (>= 7, < 8) - bolognese (~> 2.5.1) - builder (~> 3.2, >= 3.2.2) - dotenv (~> 2.1, >= 2.1.1) - maremma (>= 5.0) - namae (~> 1.0.1) - nokogiri (>= 1.16.4) + open-uri (0.5.0) + stringio + time + uri + optimist (3.2.1) + orcid_client (0.18.0) + activesupport (~> 8.1, >= 8.1.2) + bolognese (~> 2.6.0) + builder (~> 3.3) + dotenv (~> 3.2) + maremma (~> 6.0) + namae (~> 1.2) + nokogiri (>= 1.19.1, >= 1.19) orm_adapter (0.5.0) + ostruct (0.6.3) parallel (1.22.1) - parser (3.1.2.1) + parser (3.3.10.2) ast (~> 2.4.1) - postrank-uri (1.1) - addressable (>= 2.4.0) - nokogiri (>= 1.8.0) - public_suffix (>= 4.0.0, < 5) + racc pp (0.6.3) prettyprint prettyprint (0.2.0) - prism (1.7.0) + prism (1.9.0) promise.rb (0.7.4) psych (5.3.1) date stringio public_suffix (4.0.7) racc (1.8.1) - rack (2.2.21) - rack-cors (1.1.1) - rack (>= 2.0.0) - rack-jwt (0.4.0) - jwt (~> 2.0) - rack (>= 1.6.0) + rack (2.2.22) rack-protection (2.0.8.1) rack rack-session (1.0.2) rack (< 3) rack-test (2.2.0) rack (>= 1.3) - rack-utf8_sanitizer (1.7.0) - rack (>= 1.0, < 3.0) rackup (1.0.1) rack (< 3) webrick - rails (7.2.3) - actioncable (= 7.2.3) - actionmailbox (= 7.2.3) - actionmailer (= 7.2.3) - actionpack (= 7.2.3) - actiontext (= 7.2.3) - actionview (= 7.2.3) - activejob (= 7.2.3) - activemodel (= 7.2.3) - activerecord (= 7.2.3) - activestorage (= 7.2.3) - activesupport (= 7.2.3) + rails (8.1.2) + actioncable (= 8.1.2) + actionmailbox (= 8.1.2) + actionmailer (= 8.1.2) + actionpack (= 8.1.2) + actiontext (= 8.1.2) + actionview (= 8.1.2) + activejob (= 8.1.2) + activemodel (= 8.1.2) + activerecord (= 8.1.2) + activestorage (= 8.1.2) + activesupport (= 8.1.2) bundler (>= 1.15.0) - railties (= 7.2.3) + railties (= 8.1.2) rails-dom-testing (2.3.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.2) - loofah (~> 2.21) + 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 (7.2.3) - actionpack (= 7.2.3) - activesupport (= 7.2.3) - cgi + railties (8.1.2) + actionpack (= 8.1.2) + activesupport (= 8.1.2) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) @@ -552,14 +542,12 @@ GEM tsort (>= 0.2) zeitwerk (~> 2.6) rainbow (3.1.1) - rake (12.3.3) + rake (13.3.1) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) - rchardet (1.8.0) - rdf (3.3.2) + rdf (3.3.1) bcp47_spec (~> 0.2) - bigdecimal (~> 3.1, >= 3.1.5) link_header (~> 0.0, >= 0.0.8) rdf-rdfxml (3.3.0) builder (~> 3.2, >= 3.2.4) @@ -574,80 +562,70 @@ GEM rdf-xsd (3.3.0) rdf (~> 3.3) rexml (~> 3.2) - rdoc (7.0.1) + rdoc (7.2.0) erb psych (>= 4.0.0) tsort redis (4.4.0) - regexp_parser (2.1.1) + regexp_parser (2.11.3) reline (0.6.3) io-console (~> 0.5) - remotipart (1.4.4) - repost (0.3.8) + repost (0.5.1) request_store (1.5.0) rack (>= 1.4) responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rest-client (2.1.0) - http-accept (>= 1.7.0, < 2.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 4.0) - netrc (~> 0.8) rexml (3.2.5) - rouge (3.26.1) - rspec (3.13.0) - rspec-core (~> 3.13.0) - rspec-expectations (~> 3.13.0) - rspec-mocks (~> 3.13.0) - rspec-benchmark (0.4.0) - benchmark-perf (~> 0.4.0) - benchmark-trend (~> 0.2.0) - rspec (>= 3.0.0, < 4.0.0) + rouge (4.7.0) rspec-core (3.13.0) rspec-support (~> 3.13.0) rspec-expectations (3.13.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-graphql_matchers (2.0.0.pre.rc.0) - graphql (~> 2.0) - rspec (~> 3.0) rspec-mocks (3.13.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (6.1.2) - actionpack (>= 6.1) - activesupport (>= 6.1) - railties (>= 6.1) - rspec-core (~> 3.13) - rspec-expectations (~> 3.13) - rspec-mocks (~> 3.13) - rspec-support (~> 3.13) + rspec-rails (8.0.4) + actionpack (>= 7.2) + activesupport (>= 7.2) + railties (>= 7.2) + rspec-core (>= 3.13.0, < 5.0.0) + rspec-expectations (>= 3.13.0, < 5.0.0) + rspec-mocks (>= 3.13.0, < 5.0.0) + rspec-support (>= 3.13.0, < 5.0.0) rspec-support (3.13.1) - rubocop (1.38.0) + rubocop (1.85.1) json (~> 2.3) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + mcp (~> 0.6) parallel (~> 1.10) - parser (>= 3.1.2.1) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.23.0, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.23.0) - parser (>= 3.1.1.0) - rubocop-packaging (0.5.2) - rubocop (>= 1.33, < 2.0) - rubocop-performance (1.6.1) - rubocop (>= 0.71.0) - rubocop-rails (2.17.2) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.49.1) + parser (>= 3.3.7.2) + prism (~> 1.7) + rubocop-packaging (0.6.0) + lint_roller (~> 1.1.0) + rubocop (>= 1.72.1, < 2.0) + rubocop-performance (1.26.1) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) + rubocop-rails (2.34.3) activesupport (>= 4.2.0) + lint_roller (~> 1.1) rack (>= 1.1) - rubocop (>= 1.33.0, < 2.0) - rubocop-rspec (2.15.0) - rubocop (~> 1.33) - ruby-enum (0.9.0) - i18n + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) + rubocop-rspec (3.9.0) + lint_roller (~> 1.1) + rubocop (~> 1.81) ruby-progressbar (1.11.0) ruby_dig (0.0.2) sanitize (6.1.0) @@ -655,72 +633,73 @@ GEM nokogiri (>= 1.12.0) scanf (1.0.0) securerandom (0.4.1) - sentry-raven (3.1.2) - faraday (>= 1.0) - shoryuken (7.0.0) + sentry-rails (6.4.1) + railties (>= 5.2.0) + sentry-ruby (~> 6.4.1) + sentry-ruby (6.4.1) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + logger + set (1.1.2) + shoryuken (7.0.1) aws-sdk-sqs (>= 1.66.0) concurrent-ruby thor zeitwerk (~> 2.6) - shoulda-matchers (4.5.1) - activesupport (>= 4.2.0) - simple_form (4.1.0) - actionpack (>= 5.0) - activemodel (>= 5.0) + shoulda-matchers (7.0.1) + activesupport (>= 7.1) + simple_form (5.4.1) + actionpack (>= 7.0) + activemodel (>= 7.0) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) - sixarm_ruby_unaccent (1.2.0) - sort_alphabetical (1.1.0) - unicode_utils (>= 1.2.2) - spring (4.2.1) - spring-commands-rspec (1.0.4) - spring (>= 0.9.1) + singleton (0.3.0) + snaky_hash (2.0.3) + hashie (>= 0.1.0, < 6) + version_gem (>= 1.1.8, < 3) + spring (4.4.2) spring-watcher-listen (2.1.0) listen (>= 2.7, < 4.0) spring (>= 4) - sprockets (3.7.3) - base64 + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) + logger + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.2) + actionpack (>= 6.1) + activesupport (>= 6.1) sprockets (>= 3.0.0) stringio (3.2.0) - strip_attributes (1.13.0) - activemodel (>= 3.0, < 8.0) + strip_attributes (1.14.1) + activemodel (>= 3.0, < 9.0) sxp (2.0.0) matrix (~> 0.4) rdf (~> 3.3) - test-prof (0.10.2) + test-prof (1.5.2) thor (1.5.0) - timeout (0.6.0) + time (0.4.2) + date + timeout (0.6.1) tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - tzinfo-data (1.2021.2) + tzinfo-data (1.2026.1) tzinfo (>= 1.0.0) - uglifier (2.7.2) - execjs (>= 0.3.0) - json (>= 1.8.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.8) - unicode-display_width (2.3.0) - unicode-types (1.10.0) - unicode_utils (1.4.0) - uri (0.13.0) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.2.0) + unicode-types (1.11.0) + uri (1.1.1) useragent (0.16.11) - validates_email_format_of (1.6.3) - i18n - vcr (6.2.0) + vcr (6.4.0) + version_gem (1.1.9) warden (1.2.9) rack (>= 2.0.9) - webmock (3.14.0) + webmock (3.26.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) @@ -729,119 +708,94 @@ GEM base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - with_env (1.1.0) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.7.4) - zlib (2.1.1) + zeitwerk (2.7.5) + zlib (3.2.3) PLATFORMS ruby DEPENDENCIES - aasm (~> 5.0, >= 5.0.6) - active_model_serializers (~> 0.10.10) - addressable (~> 2.7) - apollo-federation (~> 1.0) - aws-sdk-s3 - aws-sdk-sqs (~> 1.23, >= 1.23.1) - base32-crockford-checksum (~> 0.2.3) - batch-loader (~> 1.4, >= 1.4.1) - better_errors - binding_of_caller - bootsnap (~> 1.4, >= 1.4.4) - byebug - cancancan (~> 3.0) - capybara (~> 3.31) - capybara-screenshot (~> 1.0, >= 1.0.24) - coffee-rails (~> 4.1, >= 4.1.1) - commonmarker (~> 0.21.0) - config (~> 5.4) - connection_pool (< 3.0) - country_select (~> 4.0) - cuprite (~> 0.9) - dalli (~> 2.7, >= 2.7.10) + aasm (~> 5.5, >= 5.5.2) + active_model_serializers (~> 0.10.16) + addressable (~> 2.8, >= 2.8.9) + apollo-federation (~> 3.10, >= 3.10.3) + aws-sdk-s3 (~> 1.215) + aws-sdk-sqs (~> 1.111) + better_errors (~> 2.10, >= 2.10.1) + binding_of_caller (~> 2.0) + bootsnap (~> 1.23) + byebug (~> 13.0) + cancancan (~> 3.6, >= 3.6.1) + capybara (~> 3.40) + capybara-screenshot (~> 1.0, >= 1.0.27) + config (~> 5.6, >= 5.6.1) + connection_pool (~> 3.0, >= 3.0.2) + cuprite (~> 0.17) + dalli (~> 5.0, >= 5.0.2) database_cleaner-active_record (~> 2.2, >= 2.2.2) - devise (~> 4.8, >= 4.8.1) - dotenv (~> 2.7, >= 2.7.5) - elasticsearch (~> 7.1.0) - elasticsearch-extensions (~> 0.0.29) - elasticsearch-model (~> 7.0) - elasticsearch-rails (~> 7.0) + devise (~> 5.0, >= 5.0.2) + dotenv (~> 3.2) + elastic-transport (~> 8.0, >= 8.0.1) + elasticsearch (~> 8.19, >= 8.19.3) + elasticsearch-model (~> 8.0, >= 8.0.1) + elasticsearch-rails (~> 8.0, >= 8.0.1) email_spec (~> 2.2) - factory_bot_rails (~> 4.8, >= 4.8.2) + factory_bot_rails (~> 6.5, >= 6.5.1) faraday_middleware-aws-sigv4 (~> 0.3.0) - flipper (~> 1.3) - flipper-active_support_cache_store - flipper-api - flipper-redis - flipper-ui - git (~> 1.5) - google-protobuf (= 3.19.6) - graphql (~> 2.0.0) - graphql-batch (~> 0.5.1) - gravtastic (~> 3.2, >= 3.2.6) - hashdiff (>= 1.0.0.beta1, < 2.0.0) - hashie + flipper (~> 1.4) + flipper-active_support_cache_store (~> 1.4) + flipper-redis (~> 1.4) + flipper-ui (~> 1.4) + google-protobuf (= 4.34) + graphql (~> 2.5, >= 2.5.21) + graphql-batch (~> 0.6.1) + hashie (~> 5.1) jsonapi-serializer (~> 2.2) - jwt (~> 2.2, >= 2.2.1) - kaminari (~> 1.2) - listen (~> 3.9) - lograge (~> 0.11.2) + jwt (~> 3.1, >= 3.1.2) + kaminari (~> 1.2, >= 1.2.2) + listen (~> 3.10) + lograge (~> 0.14.0) logstash-event (~> 1.2, >= 1.2.02) logstash-logger (~> 0.26.1) - mailgun-ruby (~> 1.2) - maremma (~> 5.0) - mini_magick (~> 4.5, >= 4.5.1) - msgpack (~> 1.4.4) - mysql2 (~> 0.5.0) - namae (~> 1.0, >= 1.0.1) - nilify_blanks (~> 1.3) - nokogiri (~> 1.10, >= 1.10.7) - oauth2 (~> 1.4) - oj (>= 2.8.3) - oj_mimic_json (~> 1.0, >= 1.0.1) - omniauth (~> 2.0, >= 2.0.4) + mailgun-ruby (~> 1.4, >= 1.4.2) + maremma (~> 6.0) + mini_magick (~> 5.3, >= 5.3.1) + msgpack (~> 1.8) + mysql2 (~> 0.5.7) + namae (~> 1.2) + nokogiri (~> 1.19, >= 1.19.1) + oj (~> 3.16, >= 3.16.16) + omniauth (~> 2.1, >= 2.1.4) omniauth-github (~> 2.0) - omniauth-globus (~> 0.9.1) omniauth-orcid (~> 2.0) - omniauth-rails_csrf_protection (~> 1.0) - orcid_client (~> 0.17.1) - postrank-uri (~> 1.1) - rack-cors (~> 1.0) - rack-jwt - rack-utf8_sanitizer (~> 1.6) - rails (~> 7.2, >= 7.2.3) - rake (~> 12.0) - remotipart (~> 1.2) - repost (~> 0.3.7) - rouge (~> 3.15) - rspec-benchmark (~> 0.4.0) - rspec-graphql_matchers (= 2.0.0.pre.rc.0) - rspec-rails (~> 6.1, >= 6.1.1) - rubocop (~> 1.3, >= 1.3.1) - rubocop-packaging (~> 0.5.1) - rubocop-performance (~> 1.5, >= 1.5.1) - rubocop-rails (~> 2.8, >= 2.8.1) - rubocop-rspec (~> 2.0) - sentry-raven (~> 3.1, >= 3.1.2) - shoryuken (~> 7.0) - shoulda-matchers (~> 4.1, >= 4.1.2) - simple_form (~> 4.1.0) + omniauth-rails_csrf_protection (~> 2.0, >= 2.0.1) + orcid_client (~> 0.18.0) + rails (~> 8.1, >= 8.1.2) + rake (~> 13.3, >= 13.3.1) + repost (~> 0.5.1) + rspec-rails (~> 8.0, >= 8.0.4) + rubocop (~> 1.85, >= 1.85.1) + rubocop-packaging (~> 0.6.0) + rubocop-performance (~> 1.26, >= 1.26.1) + rubocop-rails (~> 2.34, >= 2.34.3) + rubocop-rspec (~> 3.9) + sentry-rails (~> 6.4, >= 6.4.1) + sentry-ruby (~> 6.4, >= 6.4.1) + shoryuken (~> 7.0, >= 7.0.1) + shoulda-matchers (~> 7.0, >= 7.0.1) + simple_form (~> 5.4, >= 5.4.1) simplecov (~> 0.22.0) - spring - spring-commands-rspec + spring (~> 4.4, >= 4.4.2) spring-watcher-listen (~> 2.1) - sprockets (~> 3.7, >= 3.7.2) - sprockets-rails (~> 3.2, >= 3.2.1) + sprockets (~> 4.2, >= 4.2.2) + sprockets-rails (~> 3.5, >= 3.5.2) strip_attributes (~> 1.9, >= 1.9.2) - test-prof (~> 0.10.2) - tzinfo-data (~> 1.2019, >= 1.2019.3) - uglifier (~> 2.7, >= 2.7.2) - validates_email_format_of (~> 1.6, >= 1.6.3) - vcr (~> 6.1) - webmock (~> 3.1) - with_env (~> 1.1) + test-prof (~> 1.5, >= 1.5.2) + tzinfo-data (~> 1.2026, >= 1.2026.1) + vcr (~> 6.4) + webmock (~> 3.26, >= 3.26.1) BUNDLED WITH 2.6.9 diff --git a/README.md b/README.md index ebb42fa8..d2d138d1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://travis-ci.org/datacite/volpino.svg)](https://travis-ci.org/datacite/volpino) [![Code Climate](https://codeclimate.com/github/datacite/volpino/badges/gpa.svg)](https://codeclimate.com/github/datacite/volpino) [![Test Coverage](https://codeclimate.com/github/datacite/volpino/badges/coverage.svg)](https://codeclimate.com/github/datacite/volpino/coverage) -The DataCite service for user accounts. Users are authenticated via Globus Auth. Single-sign to various DataCite services via JWT. +The DataCite service for user accounts. Users are authenticated via Orcid Auth. Single-sign to various DataCite services via JWT. ## Installation diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 00000000..7d52bcf3 --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../stylesheets .css +//= link_directory ../javascripts .js diff --git a/app/controllers/base_controller.rb b/app/controllers/base_controller.rb index 18786943..7f494fce 100644 --- a/app/controllers/base_controller.rb +++ b/app/controllers/base_controller.rb @@ -22,7 +22,7 @@ class BaseController < ApplicationController serialization_scope :current_ability skip_before_action :verify_authenticity_token - before_action :default_format_json, :transform_params, :set_raven_context + before_action :default_format_json, :transform_params, :set_sentry_context after_action :set_jsonp_format, :set_consumer_header # from https://github.com/spree/spree/blob/master/api/app/controllers/spree/api/base_controller.rb @@ -103,7 +103,7 @@ def token_from_request_headers elsif ["JSON::ParserError", "Nokogiri::XML::SyntaxError", "ActionDispatch::Http::Parameters::ParseError"].include?(exception.class.to_s) message = exception.message else - Raven.capture_exception(exception) + Sentry.capture_exception(exception) message = exception.message end @@ -125,15 +125,15 @@ def current_ability # current_user && %w(staff_admin staff_user).include?(current_user.role) # end - def set_raven_context + def set_sentry_context if current_user.try(:uid) - Raven.user_context( + Sentry.set_user( email: current_user.email, id: current_user.uid, ip_address: request.ip, ) else - Raven.user_context( + Sentry.set_user( ip_address: request.ip, ) end diff --git a/app/controllers/claims_controller.rb b/app/controllers/claims_controller.rb index 0a916558..42513d6f 100644 --- a/app/controllers/claims_controller.rb +++ b/app/controllers/claims_controller.rb @@ -88,8 +88,8 @@ def index else render json: ClaimSerializer.new(response.results, options).serializable_hash.to_json, status: :ok end - rescue Elasticsearch::Transport::Transport::Errors::BadRequest => e - Raven.capture_exception(e) + rescue Elastic::Transport::Transport::Errors::BadRequest => e + Sentry.capture_exception(e) message = JSON.parse(e.message[6..-1]).to_h.dig("error", "root_cause", 0, "reason") diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index cd0e52bd..9ad8f57c 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -32,7 +32,7 @@ def orcid if current_user.present? @user = current_user else - @user = User.from_omniauth(auth, provider: "globus") + @user = User.from_omniauth(auth, provider: "orcid") end if Time.zone.now > @user.expires_at || omniauth.present? diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 948af989..dfce078c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -82,8 +82,8 @@ def index else render json: UserSerializer.new(response.results, options).serializable_hash.to_json, status: :ok end - rescue Elasticsearch::Transport::Transport::Errors::BadRequest => e - Raven.capture_exception(e) + rescue Elastic::Transport::Transport::Errors::BadRequest => e + Sentry.capture_exception(e) message = JSON.parse(e.message[6..-1]).to_h.dig("error", "root_cause", 0, "reason") @@ -114,7 +114,7 @@ def update @user.assign_attributes(safe_params) status = :ok else - @user = User.new(safe_params.merge(uid: params[:id], provider: "globus")) + @user = User.new(safe_params.merge(uid: params[:id], provider: "orcid")) authorize! :new, @user status = :created end diff --git a/app/graphql/volpino_schema.rb b/app/graphql/volpino_schema.rb index a236e055..d1f1f09b 100644 --- a/app/graphql/volpino_schema.rb +++ b/app/graphql/volpino_schema.rb @@ -22,7 +22,7 @@ class VolpinoSchema < GraphQL::Schema end rescue_from StandardError do |exception| - Raven.capture_exception(exception) + Sentry.capture_exception(exception) message = Rails.env.production? ? "We are sorry, but an error has occured. This problem has been logged and support has been notified. Please try again later. If the error persists please contact support." : exception.message raise GraphQL::ExecutionError, message end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 5b2599af..9b0c9fef 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -16,88 +16,6 @@ def icon(icon, text = nil, html_options = {}) html end - def markdown(text) - text = CommonMarker.render_html(text) - syntax_highlighter(text).html_safe - end - - def syntax_highlighter(html) - formatter = Rouge::Formatters::HTML.new(css_class: "hll") - lexer = Rouge::Lexers::Shell.new - - doc = Nokogiri::HTML::DocumentFragment.parse(html) - doc.search("//pre").each { |pre| pre.replace formatter.format(lexer.lex(pre.text)) } - doc.to_s - end - - def public_text - if !user_signed_in? - "panel-default" - elsif current_user.is_public - "panel-success" - else - "panel-warning" - end - end - - def auto_update_text - if !user_signed_in? - "panel-default" - elsif current_user.auto_update - "panel-success" - else - "panel-warning" - end - end - - def email_text - if current_user.has_email? - "success" - else - "warning" - end - end - - def claim_text - if current_user.claims.failed.count > 0 - "panel-warning" - elsif current_user.claims.done.count > 0 - "panel-success" - elsif current_user.claims.stale.count > 0 - "panel-info" - else - "panel-default" - end - end - - def true_text - if !user_signed_in? - "" - elsif current_user.is_public - 'true' - else - 'false' - end - end - - def enabled_text - if !user_signed_in? - "" - elsif current_user.auto_update - 'enabled' - else - 'disabled' - end - end - - def subscribed_text - if current_user.has_email? - 'subscribed' - else - 'not subscribed' - end - end - def devise_current_user @devise_current_user ||= warden.authenticate(scope: :user) end @@ -111,15 +29,6 @@ def current_user end end - def human_source_name(source_id) - sources.fetch(source_id, nil) - end - - def sources - { "orcid_search" => "ORCID Search and Link", - "orcid_update" => "ORCID Auto-Update" } - end - def aasm_states ["waiting", "working", "done", "failed", "ignored", "notified"] end @@ -128,14 +37,6 @@ def settings Settings[ENV["MODE"]] end - def worker_label(status) - case status - when "working" then "panel-success" - when "waiting" then "panel-default" - else "panel-warning" - end - end - def state_label(state) case state when "done" then "label-success" diff --git a/app/jobs/claim_import_by_id_job.rb b/app/jobs/claim_import_by_id_job.rb index 788bcfb9..26c83984 100644 --- a/app/jobs/claim_import_by_id_job.rb +++ b/app/jobs/claim_import_by_id_job.rb @@ -3,7 +3,7 @@ class ClaimImportByIdJob < ApplicationJob queue_as :volpino - rescue_from ActiveJob::DeserializationError, Elasticsearch::Transport::Transport::Errors::BadRequest do |error| + rescue_from ActiveJob::DeserializationError, Elastic::Transport::Transport::Errors::BadRequest do |error| Rails.logger.error error.message end diff --git a/app/jobs/index_job.rb b/app/jobs/index_job.rb index 5f8c4f10..c6bb11a9 100644 --- a/app/jobs/index_job.rb +++ b/app/jobs/index_job.rb @@ -3,7 +3,7 @@ class IndexJob < ApplicationJob queue_as :volpino - rescue_from ActiveJob::DeserializationError, SocketError, Elasticsearch::Transport::Transport::Errors::BadRequest do |error| + rescue_from ActiveJob::DeserializationError, SocketError, Elastic::Transport::Transport::Errors::BadRequest do |error| Rails.logger.error error.message end diff --git a/app/jobs/user_import_by_id_job.rb b/app/jobs/user_import_by_id_job.rb index 6271e439..11f748d2 100644 --- a/app/jobs/user_import_by_id_job.rb +++ b/app/jobs/user_import_by_id_job.rb @@ -3,7 +3,7 @@ class UserImportByIdJob < ApplicationJob queue_as :volpino - rescue_from ActiveJob::DeserializationError, Elasticsearch::Transport::Transport::Errors::BadRequest do |error| + rescue_from ActiveJob::DeserializationError, Elastic::Transport::Transport::Errors::BadRequest do |error| Rails.logger.error error.message end diff --git a/app/models/claim.rb b/app/models/claim.rb index eb3f4be7..a5efa413 100644 --- a/app/models/claim.rb +++ b/app/models/claim.rb @@ -336,7 +336,6 @@ def self.import_by_id(options = {}) Claim.where(id: id..(id + 499)).find_in_batches(batch_size: 500) do |claims| response = Claim.__elasticsearch__.client.bulk \ index: index, - type: Claim.document_type, body: claims.map { |claim| { index: { _id: claim.id, data: claim.as_indexed_json } } } # try to handle errors @@ -357,7 +356,7 @@ def self.import_by_id(options = {}) end count - rescue Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge, Faraday::ConnectionFailed, ActiveRecord::LockWaitTimeout => e + rescue Elastic::Transport::Transport::Errors::RequestEntityTooLarge, Faraday::ConnectionFailed, ActiveRecord::LockWaitTimeout => e Rails.logger.error "[Elasticsearch] Error #{e.message} importing claims with IDs #{id} - #{(id + 499)}." count = 0 diff --git a/app/models/concerns/indexable.rb b/app/models/concerns/indexable.rb index 057d391a..8adb1bf6 100644 --- a/app/models/concerns/indexable.rb +++ b/app/models/concerns/indexable.rb @@ -18,7 +18,7 @@ module Indexable before_destroy do __elasticsearch__.delete_document - rescue Elasticsearch::Transport::Transport::Errors::NotFound + rescue Elastic::Transport::Transport::Errors::NotFound nil end end diff --git a/app/models/concerns/resolvable.rb b/app/models/concerns/resolvable.rb index 92f45f50..3f501990 100644 --- a/app/models/concerns/resolvable.rb +++ b/app/models/concerns/resolvable.rb @@ -7,12 +7,22 @@ module Resolvable require "addressable/uri" def get_normalized_url(url) - url = PostRank::URI.clean(url) - if PostRank::URI.valid?(url) - url + uri = Addressable::URI.parse(url) + return nil if uri.host.blank? + + uri.normalize! + + if uri.query_values + uri.query_values = uri.query_values.reject do |k, _| + k.match?(/^utm_|^ref$|^source$/) + end end - rescue Addressable::URI::InvalidURIError => e - { error: e.message } + + uri.fragment = nil # optional: remove #stuff + + uri.to_s + rescue Addressable::URI::InvalidURIError + nil end def doi_as_url(doi) diff --git a/app/models/heartbeat.rb b/app/models/heartbeat.rb index 3ff77432..d4565f26 100644 --- a/app/models/heartbeat.rb +++ b/app/models/heartbeat.rb @@ -21,7 +21,7 @@ def services_up? def memcached_up? host = ENV["MEMCACHE_SERVERS"] || ENV["HOSTNAME"] - memcached_client = Dalli::Client.new("#{host}:11211") + memcached_client = Dalli::Client.new("#{host}:11211", serializer: JSON) memcached_client.alive! true rescue StandardError diff --git a/app/models/user.rb b/app/models/user.rb index f256b7ce..b2650484 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -20,8 +20,17 @@ class User < ApplicationRecord include Elasticsearch::Model - nilify_blanks - strip_attributes only: %i[given_names family_name name other_names] + strip_attributes except: %i[ + authentication_token + confirmation_token + github_token + orcid_token + orcid_auto_update_access_token + orcid_auto_update_refresh_token + orcid_search_and_link_access_token + orcid_search_and_link_refresh_token + ], + collapse_spaces: true # include hash helper include Hashie::Extensions::DeepFetch @@ -38,7 +47,7 @@ class User < ApplicationRecord has_many :claims, primary_key: "uid", foreign_key: "orcid", inverse_of: :user - devise :omniauthable, omniauth_providers: %i[orcid github globus] + devise :omniauthable, omniauth_providers: %i[orcid github] validates :uid, presence: true, uniqueness: { case_sensitive: false } validate :validate_email @@ -170,7 +179,6 @@ def self.import_by_id(options = {}) User.where(id: id..(id + 499)).find_in_batches(batch_size: 500) do |users| response = User.__elasticsearch__.client.bulk \ index: index, - type: User.document_type, body: users.map { |user| { index: { _id: user.id, data: user.as_indexed_json } } } # try to handle errors @@ -191,7 +199,7 @@ def self.import_by_id(options = {}) end count - rescue Elasticsearch::Transport::Transport::Errors::RequestEntityTooLarge, Faraday::ConnectionFailed, ActiveRecord::LockWaitTimeout => e + rescue Elastic::Transport::Transport::Errors::RequestEntityTooLarge, Faraday::ConnectionFailed, ActiveRecord::LockWaitTimeout => e Rails.logger.info "[Elasticsearch] Error #{e.message} importing users with IDs #{id} - #{(id + 499)}." count = 0 @@ -422,9 +430,6 @@ def process_data(options = {}) if result.body["skip"] elsif result.body["errors"] - # send notification to Sentry - # Raven.capture_exception(RuntimeError.new(result.body["errors"].first["title"]))if ENV["SENTRY_DSN"] - logger.error result.body["errors"].inspect else write_attribute(:github_put_code, result.body["put_code"]) diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d0f0675d..00f34419 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -27,6 +27,5 @@
<% end %> - <%= render partial: "layouts/#{ENV['MODE']}/footer" -%> diff --git a/bin/ci b/bin/ci new file mode 100755 index 00000000..4137ad5b --- /dev/null +++ b/bin/ci @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "active_support/continuous_integration" + +CI = ActiveSupport::ContinuousIntegration +require_relative "../config/ci.rb" diff --git a/bin/dev b/bin/dev new file mode 100755 index 00000000..5f91c205 --- /dev/null +++ b/bin/dev @@ -0,0 +1,2 @@ +#!/usr/bin/env ruby +exec "./bin/rails", "server", *ARGV diff --git a/bin/rubocop b/bin/rubocop index 40330c0f..5a205047 100755 --- a/bin/rubocop +++ b/bin/rubocop @@ -2,7 +2,7 @@ require "rubygems" require "bundler/setup" -# explicit rubocop config increases performance slightly while avoiding config confusion. +# Explicit RuboCop config increases performance slightly while avoiding config confusion. ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__)) load Gem.bin_path("rubocop", "rubocop") diff --git a/bin/setup b/bin/setup index b617f006..81be011e 100755 --- a/bin/setup +++ b/bin/setup @@ -2,7 +2,6 @@ require "fileutils" APP_ROOT = File.expand_path("..", __dir__) -APP_NAME = "volpino" def system!(*args) system(*args, exception: true) @@ -14,7 +13,6 @@ FileUtils.chdir APP_ROOT do # Add necessary setup steps to this file. puts "== Installing dependencies ==" - system! "gem install bundler --conservative" system("bundle check") || system!("bundle install") # puts "\n== Copying sample files ==" @@ -24,10 +22,14 @@ FileUtils.chdir APP_ROOT do puts "\n== Preparing database ==" system! "bin/rails db:prepare" + system! "bin/rails db:reset" if ARGV.include?("--reset") puts "\n== Removing old logs and tempfiles ==" system! "bin/rails log:clear tmp:clear" - puts "\n== Restarting application server ==" - system! "bin/rails restart" + unless ARGV.include?("--skip-server") + puts "\n== Starting development server ==" + STDOUT.flush # flush the output before exec(2) so that it displays + exec "bin/dev" + end end diff --git a/config/application.rb b/config/application.rb index e94da337..cd994893 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require_relative "boot" require "rails/all" @@ -112,5 +110,6 @@ class Application < Rails::Application Rails.env end config.active_job.queue_name_prefix = queue_name_prefix + config.active_storage.variant_processor = :disabled end end diff --git a/config/ci.rb b/config/ci.rb new file mode 100644 index 00000000..7e3f04c4 --- /dev/null +++ b/config/ci.rb @@ -0,0 +1,22 @@ +# Run using bin/ci + +CI.run do + step "Setup", "bin/setup --skip-server" + + step "Style: Ruby", "bin/rubocop" + + step "Security: Importmap vulnerability audit", "bin/importmap audit" + step "Tests: Rails", "bin/rails test" + step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant" + + # Optional: Run system tests + # step "Tests: System", "bin/rails test:system" + + # Optional: set a green GitHub commit status to unblock PR merge. + # Requires the `gh` CLI and `gh extension install basecamp/gh-signoff`. + # if success? + # step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff" + # else + # failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again." + # end +end diff --git a/config/environments/development.rb b/config/environments/development.rb index 5c93e005..9c20c081 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,5 +1,3 @@ -# frozen_string_literal: true - require "active_support/core_ext/integer/time" Rails.application.configure do @@ -10,12 +8,17 @@ # 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. config.consider_all_requests_local = true + # Enable server timing. + config.server_timing = true + # Enable/disable caching. By default caching is disabled. # Run rails dev:cache to toggle caching. if Rails.root.join("tmp", "caching-dev.txt").exist? @@ -86,6 +89,27 @@ # set Active Job queueing backend config.active_job.queue_adapter = :inline + # Append comments with runtime information tags to SQL queries in logs. + config.active_record.query_log_tags_enabled = true + + # Highlight code that enqueued background job in logs. + config.active_job.verbose_enqueue_logs = true + + # Highlight code that triggered redirect in logs. + config.action_dispatch.verbose_redirect_logs = true + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + config.action_view.annotate_rendered_view_with_filenames = true + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true + + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true + # Raises error for missing translations # config.action_view.raise_on_missing_translations = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 24a8fdce..79eff502 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,25 +1,27 @@ -# frozen_string_literal: true +require "active_support/core_ext/integer/time" Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. # Code is not reloaded between requests. - config.cache_classes = true + config.enable_reloading = false - # Eager load code on boot. This eager loads most of Rails and - # your application in memory, allowing both threaded web servers - # and those relying on copy on write to perform better. - # Rake tasks automatically ignore this option for performance. + # Eager load code on boot for better performance and memory savings (ignored by Rake tasks). config.eager_load = true - # Full error reports are disabled and caching is turned on. - config.consider_all_requests_local = false + # Full error reports are disabled. + config.consider_all_requests_local = false + + # Turn on fragment caching in view templates. config.action_controller.perform_caching = true # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). # config.require_master_key = true + # Cache assets for far-future expiry since they are all digest stamped. + config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } + # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? @@ -88,6 +90,12 @@ # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify + # Prevent health checks from clogging up the logs. + config.silence_healthcheck_path = "/heartbeat" + + # Don't log any deprecations. + config.active_support.report_deprecations = false + # Tell Active Support which deprecation messages to disallow. config.active_support.disallowed_deprecation_warnings = [] @@ -100,4 +108,7 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Only use :id for inspections in production. + config.active_record.attributes_for_inspect = [ :id ] end diff --git a/config/initializers/_shoryuken.rb b/config/initializers/_shoryuken.rb index 497d1c80..1455bf8c 100644 --- a/config/initializers/_shoryuken.rb +++ b/config/initializers/_shoryuken.rb @@ -4,11 +4,16 @@ module Shoryuken module Middleware module Server - class RavenReporter - def call(_worker_instance, queue, _sqs_msg, body) - tags = { job: body["job_class"], queue: queue } - context = { message: body } - Raven.capture(tags: tags, extra: context) { yield } + class SentryReporter + def call(worker_instance, queue, sqs_msg, body) + Sentry.with_scope do |scope| + scope.set_tags(job: body["job_class"], queue:) + scope.set_context(:message, body) + + Sentry.with_exception_captured do + yield + end + end end end end @@ -19,7 +24,7 @@ def call(_worker_instance, queue, _sqs_msg, body) config.server_middleware do |chain| # remove logging of timing events chain.remove Shoryuken::Middleware::Server::Timing - chain.add Shoryuken::Middleware::Server::RavenReporter + chain.add Shoryuken::Middleware::Server::SentryReporter end end diff --git a/config/initializers/_version.rb b/config/initializers/_version.rb deleted file mode 100644 index 1ec40221..00000000 --- a/config/initializers/_version.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module Volpino - class Application - g = Git.open(Rails.root) - begin - VERSION = g.tags.map { |t| Gem::Version.new(t.name) }.max.to_s - rescue ArgumentError - VERSION = "1.0" - end - REVISION = g.object("HEAD").sha - end -end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index f4556db3..6d56e439 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index bd5bcd2b..48732442 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -5,8 +5,3 @@ # Add additional assets to the asset load path. # Rails.application.config.assets.paths << Emoji.images_path - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in the app/assets -# folder are already added. -# Rails.application.config.assets.precompile += %w[ admin.js admin.css ] diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index d0f0d3b5..4b63f289 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index b3076b38..d51d7139 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -20,6 +20,10 @@ # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } # config.content_security_policy_nonce_directives = %w(script-src style-src) # +# # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag` +# # if the corresponding directives are specified in `content_security_policy_nonce_directives`. +# # config.content_security_policy_nonce_auto = true +# # # Report violations without enforcing the policy. # # config.content_security_policy_report_only = true # end diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb deleted file mode 100644 index 0c5dd99a..00000000 --- a/config/initializers/cors.rb +++ /dev/null @@ -1,16 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Avoid CORS issues when API is called from the frontend app. -# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin Ajax requests. - -# Read more: https://github.com/cyu/rack-cors - -# Rails.application.config.middleware.insert_before 0, Rack::Cors do -# allow do -# origins "example.com" -# -# resource "*", -# headers: :any, -# methods: [:get, :post, :put, :patch, :delete, :options, :head] -# end -# end diff --git a/config/initializers/elasticsearch.rb b/config/initializers/elasticsearch.rb index 063a4da4..a7725155 100644 --- a/config/initializers/elasticsearch.rb +++ b/config/initializers/elasticsearch.rb @@ -3,23 +3,44 @@ require "faraday" require "faraday_middleware/aws_sigv4" -if ENV["ES_HOST"] == "elasticsearch.test.datacite.org" || ENV["ES_HOST"] == "elasticsearch.datacite.org" || ENV["ES_HOST"] == "elasticsearch.stage.datacite.org" - Elasticsearch::Model.client = Elasticsearch::Client.new(host: ENV["ES_HOST"], port: "80", scheme: "http") do |f| +# Bypass Elasticsearch product check to allow OpenSearch-compatible endpoints. +# elasticsearch-ruby 8.x raises UnsupportedProductError unless the server returns +# x-elastic-product: Elasticsearch, which OpenSearch does not. +module ElasticsearchV8OpenSearchBypass + private + def verify_elasticsearch(*args, &block) + response = @transport.perform_request(*args, &block) + @verified = true + response + end +end + +Elasticsearch::Client.prepend(ElasticsearchV8OpenSearchBypass) + +if ENV["ES_HOST"].end_with?(".datacite.org") + Elasticsearch::Model.client = + Elasticsearch::Client.new( + host: ENV["ES_HOST"], + port: "80", + scheme: "http" + ) do |f| f.request :aws_sigv4, - credentials: Aws::Credentials.new(ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"]), + credentials: Aws::Credentials.new( + ENV["AWS_ACCESS_KEY_ID"], + ENV["AWS_SECRET_ACCESS_KEY"] + ), service: "es", region: ENV["AWS_REGION"] f.adapter :excon end else - # config = { - # host: ENV['ES_HOST'], - # transport_options: { - # request: { timeout: 30 } - # } - # } - Elasticsearch::Model.client = Elasticsearch::Client.new(host: ENV["ES_HOST"], port: ENV["ES_PORT"], scheme: ENV["ES_SCHEME"], user: "elastic", password: ENV["ELASTIC_PASSWORD"]) do |f| - f.adapter :excon - end + Elasticsearch::Model.client = + Elasticsearch::Client.new( + host: ENV["ES_HOST"], + port: ENV["ES_PORT"], + scheme: ENV["ES_SCHEME"], + user: "elastic", + password: ENV["ELASTIC_PASSWORD"] + ) { |f| f.adapter :excon } end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index c010b83d..c0b717f7 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -4,5 +4,5 @@ # Use this to limit dissemination of sensitive information. # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. Rails.application.config.filter_parameters += [ - :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc ] diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index 6e1d16f0..be6fedc5 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb index 7df9ce8f..c300f213 100644 --- a/config/initializers/new_framework_defaults_5_2.rb +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # Be sure to restart your server when you modify this file. # # This file contains migration options to ease your Rails 5.2 upgrade. diff --git a/config/initializers/new_framework_defaults_6_1.rb b/config/initializers/new_framework_defaults_6_1.rb index 0b4ce023..8c28549c 100644 --- a/config/initializers/new_framework_defaults_6_1.rb +++ b/config/initializers/new_framework_defaults_6_1.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # Be sure to restart your server when you modify this file. # # This file contains migration options to ease your Rails 6.1 upgrade. diff --git a/config/initializers/new_framework_defaults_7_1.rb b/config/initializers/new_framework_defaults_7_1.rb index 4ef460cb..a71adbd5 100644 --- a/config/initializers/new_framework_defaults_7_1.rb +++ b/config/initializers/new_framework_defaults_7_1.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + # Be sure to restart your server when you modify this file. # # This file eases your Rails 7.1 framework defaults upgrade. diff --git a/config/initializers/new_framework_defaults_8_1.rb b/config/initializers/new_framework_defaults_8_1.rb new file mode 100644 index 00000000..2dcf3ca7 --- /dev/null +++ b/config/initializers/new_framework_defaults_8_1.rb @@ -0,0 +1,74 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 8.1 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `8.1`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +### +# Skips escaping HTML entities and line separators. When set to `false`, the +# JSON renderer no longer escapes these to improve performance. +# +# Example: +# class PostsController < ApplicationController +# def index +# render json: { key: "\u2028\u2029<>&" } +# end +# end +# +# Renders `{"key":"\u2028\u2029\u003c\u003e\u0026"}` with the previous default, but `{"key":"<>&"}` with the config +# set to `false`. +# +# Applications that want to keep the escaping behavior can set the config to `true`. +#++ +# Rails.configuration.action_controller.escape_json_responses = false + +### +# Skips escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON. +# +# Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019. +# As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset. +#++ +# Rails.configuration.active_support.escape_js_separators_in_json = false + +### +# Raises an error when order dependent finder methods (e.g. `#first`, `#second`) are called without `order` values +# on the relation, and the model does not have any order columns (`implicit_order_column`, `query_constraints`, or +# `primary_key`) to fall back on. +# +# The current behavior of not raising an error has been deprecated, and this configuration option will be removed in +# Rails 8.2. +#++ +# Rails.configuration.active_record.raise_on_missing_required_finder_order_columns = true + +### +# Controls how Rails handles path relative URL redirects. +# When set to `:raise`, Rails will raise an `ActionController::Redirecting::UnsafeRedirectError` +# for relative URLs without a leading slash, which can help prevent open redirect vulnerabilities. +# +# Example: +# redirect_to "example.com" # Raises UnsafeRedirectError +# redirect_to "@attacker.com" # Raises UnsafeRedirectError +# redirect_to "/safe/path" # Works correctly +# +# Applications that want to allow these redirects can set the config to `:log` (previous default) +# to only log warnings, or `:notify` to send ActiveSupport notifications. +#++ +# Rails.configuration.action_controller.action_on_path_relative_redirect = :raise + +### +# Use a Ruby parser to track dependencies between Action View templates +#++ +# Rails.configuration.action_view.render_tracker = :ruby + +### +# When enabled, hidden inputs generated by `form_tag`, `token_tag`, `method_tag`, and the hidden parameter fields +# included in `button_to` forms will omit the `autocomplete="off"` attribute. +# +# Applications that want to keep generating the `autocomplete` attribute for those tags can set it to `false`. +#++ +# Rails.configuration.action_view.remove_hidden_field_autocomplete = true diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb index ded93bdb..96ee7244 100644 --- a/config/initializers/sentry.rb +++ b/config/initializers/sentry.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true -Raven.configure do |config| +Sentry.init do |config| config.dsn = ENV["SENTRY_DSN"] - config.release = "volpino:" + Volpino::Application::VERSION - config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s) + config.breadcrumbs_logger = [:active_support_logger, :http_logger] + config.traces_sample_rate = 0.5 + config.send_default_pii = true end diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 00000000..38c4b865 --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,42 @@ +# This configuration file will be evaluated by Puma. The top-level methods that +# are invoked here are part of Puma's configuration DSL. For more information +# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. +# +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. +# +# You can control the number of workers using ENV["WEB_CONCURRENCY"]. You +# should only set this value when you want to run 2 or more workers. The +# default is already 1. You can set it to `auto` to automatically start a worker +# for each available processor. +# +# The ideal number of threads per worker depends both on how much time the +# application spends waiting for IO operations and on how much you wish to +# prioritize throughput over latency. +# +# As a rule of thumb, increasing the number of threads will increase how much +# traffic a given process can handle (throughput), but due to CRuby's +# Global VM Lock (GVL) it has diminishing returns and will degrade the +# response time (latency) of the application. +# +# The default is set to 3 threads as it's deemed a decent compromise between +# throughput and latency for the average Rails application. +# +# Any libraries that use a connection pool or another resource pool should +# be configured to provide at least as many connections as the number of +# threads. This includes Active Record's `pool` parameter in `database.yml`. +threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +port ENV.fetch("PORT", 3000) + +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart + +# Run the Solid Queue supervisor inside of Puma for single-server deployments. +plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] + +# Specify the PID file. Defaults to tmp/pids/server.pid in development. +# In other environments, only set the PID file if requested. +pidfile ENV["PIDFILE"] if ENV["PIDFILE"] diff --git a/config/routes.rb b/config/routes.rb index 74edaf7d..6a54998c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -25,20 +25,6 @@ get "orcid/search_and_link/revoke", to: "users/orcid#search_and_link_revoke", as: :orcid_search_and_link_revoke end - # enable feature flags api - flipper_app = Flipper::Api.app(Flipper) do |builder| - public_key = OpenSSL::PKey::RSA.new(ENV["JWT_PUBLIC_KEY"].to_s.gsub('\n', "\n")) - builder.use Rack::JWT::Auth, secret: public_key, verify: true, options: { algorithm: "RS256" } do |payload| - return false if payload.blank? - - # check whether token has expired - return false unless Time.now.to_i < payload["exp"] - - ["staff_admin", "staff_user"].include?(payload["role_id"]) - end - end - mount flipper_app, at: "/api/flipper" - authenticate :user, lambda { |u| u.is_admin? } do mount Flipper::UI.app(Flipper) => "/flipper" end diff --git a/db/schema.rb b/db/schema.rb index a1680c89..17ab5b3e 100755 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,20 +10,20 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2026_01_06_085208) do +ActiveRecord::Schema[8.1].define(version: 2026_01_06_085208) do create_table "claims", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| - t.string "uuid", limit: 191 - t.string "doi", limit: 191 - t.integer "state_number", default: 0 - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.string "orcid", limit: 191 - t.string "source_id", limit: 191 + t.string "aasm_state", limit: 191 + t.string "claim_action", limit: 191, default: "create" t.datetime "claimed_at", precision: nil + t.datetime "created_at", precision: nil, null: false + t.string "doi", limit: 191 t.text "error_messages" - t.string "claim_action", limit: 191, default: "create" + t.string "orcid", limit: 191 t.integer "put_code" - t.string "aasm_state", limit: 191 + t.string "source_id", limit: 191 + t.integer "state_number", default: 0 + t.datetime "updated_at", precision: nil, null: false + t.string "uuid", limit: 191 t.index ["created_at"], name: "index_claims_created_at" t.index ["orcid"], name: "index_claims_uid" t.index ["put_code"], name: "index_claims_on_put_code" @@ -32,88 +32,88 @@ end create_table "funders", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| + t.datetime "created_at", precision: nil, null: false t.string "fundref_id" t.string "name" t.string "replaced" - t.datetime "created_at", precision: nil, null: false t.datetime "updated_at", precision: nil, null: false end create_table "members", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| - t.string "name", limit: 191, null: false - t.string "title", null: false - t.text "description" - t.string "member_type", limit: 191, default: "full" - t.integer "year" - t.string "region" t.string "country_code" - t.string "logo" - t.string "email" - t.string "website" - t.string "phone" t.datetime "created_at", precision: nil - t.datetime "updated_at", precision: nil + t.text "description" + t.string "email" t.string "image" t.string "institution_type", limit: 191 + t.string "logo" + t.string "member_type", limit: 191, default: "full" + t.string "name", limit: 191, null: false + t.string "phone" + t.string "region" + t.string "title", null: false + t.datetime "updated_at", precision: nil + t.string "website" + t.integer "year" t.index ["institution_type"], name: "index_member_institution_type" t.index ["name"], name: "index_members_on_name" end create_table "status", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| - t.string "uuid", limit: 191 - t.integer "users_count", default: 0 - t.integer "users_new_count", default: 0 - t.bigint "db_size", default: 0 - t.string "version" - t.string "current_version" - t.datetime "created_at", precision: nil, null: false - t.datetime "updated_at", precision: nil, null: false - t.integer "claims_search_count", default: 0 - t.integer "claims_search_new_count", default: 0 t.integer "claims_auto_count", default: 0 t.integer "claims_auto_new_count", default: 0 - t.integer "members_emea_count", default: 0 + t.integer "claims_search_count", default: 0 + t.integer "claims_search_new_count", default: 0 + t.datetime "created_at", precision: nil, null: false + t.string "current_version" + t.bigint "db_size", default: 0 t.integer "members_amer_count", default: 0 t.integer "members_apac_count", default: 0 + t.integer "members_emea_count", default: 0 + t.datetime "updated_at", precision: nil, null: false + t.integer "users_count", default: 0 + t.integer "users_new_count", default: 0 + t.string "uuid", limit: 191 + t.string "version" t.index ["created_at"], name: "index_status_created_at" end create_table "users", id: :integer, charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", options: "ENGINE=InnoDB ROW_FORMAT=DYNAMIC", force: :cascade do |t| - t.string "name", limit: 191 - t.string "family_name", limit: 191 - t.string "given_names", limit: 191 - t.string "email", limit: 191 - t.string "provider", default: "orcid" - t.string "uid", limit: 191 t.string "authentication_token", limit: 191 - t.string "role_id", default: "user" t.boolean "auto_update", default: true - t.datetime "expires_at", precision: nil, default: "1970-01-01 00:00:00", null: false - t.datetime "created_at", precision: nil - t.datetime "updated_at", precision: nil - t.text "other_names" + t.boolean "beta_tester", default: false + t.string "client_id" + t.datetime "confirmation_sent_at", precision: nil t.string "confirmation_token", limit: 191 t.datetime "confirmed_at", precision: nil - t.datetime "confirmation_sent_at", precision: nil - t.string "unconfirmed_email" + t.datetime "created_at", precision: nil + t.string "email", limit: 191 + t.datetime "expires_at", precision: nil, default: "1970-01-01 00:00:00", null: false + t.string "family_name", limit: 191 t.string "github", limit: 191 - t.string "github_uid", limit: 191 - t.string "github_token", limit: 191 t.integer "github_put_code" + t.string "github_token", limit: 191 + t.string "github_uid", limit: 191 + t.string "given_names", limit: 191 t.boolean "is_public", default: true - t.string "provider_id" - t.string "client_id" - t.string "sandbox_id" - t.boolean "beta_tester", default: false - t.string "organization", limit: 191 + t.string "name", limit: 191 t.string "orcid_auto_update_access_token", limit: 191 t.datetime "orcid_auto_update_expires_at", precision: nil, default: "1970-01-01 00:00:00" t.string "orcid_auto_update_refresh_token" - t.string "orcid_token" t.datetime "orcid_expires_at" t.string "orcid_search_and_link_access_token" - t.string "orcid_search_and_link_refresh_token" t.datetime "orcid_search_and_link_expires_at" + t.string "orcid_search_and_link_refresh_token" + t.string "orcid_token" + t.string "organization", limit: 191 + t.text "other_names" + t.string "provider", default: "orcid" + t.string "provider_id" + t.string "role_id", default: "user" + t.string "sandbox_id" + t.string "uid", limit: 191 + t.string "unconfirmed_email" + t.datetime "updated_at", precision: nil t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["family_name", "given_names"], name: "index_users_on_family_name_and_given_names" t.index ["github"], name: "index_users_on_github", unique: true diff --git a/public/400.html b/public/400.html new file mode 100644 index 00000000..640de033 --- /dev/null +++ b/public/400.html @@ -0,0 +1,135 @@ + + + + + + + The server cannot process the request due to a client error (400 Bad Request) + + + + + + + + + + + + + +
+
+ +
+
+

The server cannot process the request due to a client error. Please check the request and try again. If you're the application owner check the logs for more information.

+
+
+ + + + diff --git a/public/404.html b/public/404.html index 2be3af26..d7f0f142 100644 --- a/public/404.html +++ b/public/404.html @@ -1,67 +1,135 @@ - - - - The page you were looking for doesn't exist (404) - - - - - - -
-
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
-

If you are the application owner check the logs for more information.

-
- + + + + + + + The page you were looking for doesn't exist (404 Not found) + + + + + + + + + + + + + +
+
+ +
+
+

The page you were looking for doesn't exist. You may have mistyped the address or the page may have moved. If you're the application owner check the logs for more information.

+
+
+ + + diff --git a/public/406-unsupported-browser.html b/public/406-unsupported-browser.html index 7cf1e168..43d2811e 100644 --- a/public/406-unsupported-browser.html +++ b/public/406-unsupported-browser.html @@ -1,66 +1,135 @@ - - - - Your browser is not supported (406) - - - - - - -
-
-

Your browser is not supported.

-

Please upgrade your browser to continue.

-
-
- + + + + + + + Your browser is not supported (406 Not Acceptable) + + + + + + + + + + + + + +
+
+ +
+
+

Your browser is not supported.
Please upgrade your browser to continue.

+
+
+ + + diff --git a/public/422.html b/public/422.html index c08eac0d..f12fb4aa 100644 --- a/public/422.html +++ b/public/422.html @@ -1,67 +1,135 @@ - - - - The change you wanted was rejected (422) - - - - - - -
-
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
-

If you are the application owner check the logs for more information.

-
- + + + + + + + The change you wanted was rejected (422 Unprocessable Entity) + + + + + + + + + + + + + +
+
+ +
+
+

The change you wanted was rejected. Maybe you tried to change something you didn't have access to. If you're the application owner check the logs for more information.

+
+
+ + + diff --git a/public/500.html b/public/500.html index 78a030af..e4eb18a7 100644 --- a/public/500.html +++ b/public/500.html @@ -1,66 +1,135 @@ - - - - We're sorry, but something went wrong (500) - - - - - - -
-
-

We're sorry, but something went wrong.

-
-

If you are the application owner check the logs for more information.

-
- + + + + + + + We're sorry, but something went wrong (500 Internal Server Error) + + + + + + + + + + + + + +
+
+ +
+
+

We're sorry, but something went wrong.
If you're the application owner check the logs for more information.

+
+
+ + + diff --git a/public/icon.png b/public/icon.png index f3b5abcb..c4c9dbfb 100644 Binary files a/public/icon.png and b/public/icon.png differ diff --git a/public/icon.svg b/public/icon.svg index 78307ccd..04b34bf8 100644 --- a/public/icon.svg +++ b/public/icon.svg @@ -1,3 +1,3 @@ - - + + diff --git a/spec/factories/default.rb b/spec/factories/default.rb index dd704c0c..5ea72f97 100644 --- a/spec/factories/default.rb +++ b/spec/factories/default.rb @@ -3,7 +3,7 @@ FactoryBot.define do factory :user do sequence(:name) { |_n| "Josiah Carberry{n}" } - provider { "globus" } + provider { "orcid" } role_id { "user" } sequence(:uid) { |n| "0000-0002-1825-000#{n}" } diff --git a/spec/lib/tasks/import_rake_spec.rb b/spec/lib/tasks/import_rake_spec.rb index 467cb440..0a169486 100644 --- a/spec/lib/tasks/import_rake_spec.rb +++ b/spec/lib/tasks/import_rake_spec.rb @@ -20,7 +20,6 @@ describe "import:one", vcr: true, rake: true, elasticsearch: true do include ActiveJob::TestHelper - include WithEnv include_context "rake" let(:user) { FactoryBot.create(:user, uid: "0000-0003-1419-2405") } @@ -31,8 +30,12 @@ end it "should run" do - with_env("ORCID" => "0000-0003-1419-2405") do - expect(capture_stdout { subject.invoke }).to eq(output) - end + had_orcid = ENV.key?("ORCID") + original_orcid = ENV["ORCID"] + + ENV["ORCID"] = "0000-0003-1419-2405" + expect(capture_stdout { subject.invoke }).to eq(output) + ensure + had_orcid ? ENV["ORCID"] = original_orcid : ENV.delete("ORCID") end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ce230422..81c260d6 100755 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -8,10 +8,27 @@ it { is_expected.to validate_uniqueness_of(:uid).case_insensitive } it { is_expected.to have_many(:claims) } - it { is_expected.to strip_attribute :given_names } - it { is_expected.to strip_attribute :family_name } - it { is_expected.to strip_attribute :other_names } - it { is_expected.to strip_attribute :name } + it { is_expected.to strip_attribute(:given_names).collapse_spaces } + it { is_expected.to strip_attribute(:family_name).collapse_spaces } + it { is_expected.to strip_attribute(:name).collapse_spaces } + + + describe "attribute normalization" do + it "converts empty strings to nil" do + user = User.new(name: " ", given_names: "", family_name: " ") + user.valid? + expect(user.name).to be_nil + expect(user.given_names).to be_nil + expect(user.family_name).to be_nil + end + + it "preserves non-empty values" do + user = User.new(name: " John Doe ", given_names: " John ") + user.valid? + expect(user.name).to eq("John Doe") + expect(user.given_names).to eq("John") + end + end describe "jwt" do subject { FactoryBot.create(:regular_user) } @@ -31,34 +48,9 @@ end end - # describe 'push_github_identifier', :order => :defined do - # let(:put_code) { 5583 } - # it 'no errors' do - # expect(subject.github_to_be_created?).to be true - # response = subject.push_github_identifier - # expect(response.body["put_code"]).to eq(put_code) - # expect(response.status).to eq(201) - # end - - # it 'delete claim' do - # subject = FactoryBot.create(:valid_user, github: "mfenner", github_put_code: put_code) - # expect(subject.github_to_be_deleted?).to be true - # response = subject.push_github_identifier - # expect(response.body["data"]).to be_blank - # expect(response.body["errors"]).to be_nil - # expect(response.status).to eq(204) - # end - # end - describe "process_data", order: :defined do let(:put_code) { 5582 } - # it 'no errors' do - # subject = FactoryBot.create(:valid_user, github: "mfenner", github_put_code: nil) - # expect(subject.process_data).to be true - # expect(subject.github_put_code).to eq(put_code) - # end - it "delete claim" do subject = FactoryBot.create(:valid_user, github: "mfenner", github_put_code: put_code) expect(subject.process_data).to_not(eq(nil)) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 8b43920f..58192801 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -23,7 +23,6 @@ require "rack/test" require "aasm/rspec" require "devise" -require "colorize" require "maremma" require "strip_attributes/matchers" diff --git a/spec/requests/claims_spec.rb b/spec/requests/claims_spec.rb index 8b52bfc1..16421aa5 100644 --- a/spec/requests/claims_spec.rb +++ b/spec/requests/claims_spec.rb @@ -155,7 +155,7 @@ let(:claim) { FactoryBot.build(:claim, uuid: "c7a026ca-51f9-4be9-b3fb-c15580f98e58", orcid: "0000-0002-1825-0097", source_id: nil) } let(:params) do { "claim" => { "uuid" => claim.uuid, - "orcid" => claim.orcid, + "orcid" => user.orcid, "doi" => claim.doi } } end @@ -196,7 +196,7 @@ expect(last_response.status).to eq(422) response = JSON.parse(last_response.body) - expect(response["errors"].first["title"]).to start_with("param is missing or the value is empty: claim") + expect(response["errors"].first["title"]).to start_with("param is missing or the value is empty or invalid: claim") end end diff --git a/spec/support/elasticsearch_helper.rb b/spec/support/elasticsearch_helper.rb index b05e955e..20a358c6 100644 --- a/spec/support/elasticsearch_helper.rb +++ b/spec/support/elasticsearch_helper.rb @@ -6,7 +6,7 @@ RSpec.configure do |config| config.around :example, elasticsearch: true do |example| SEARCHABLE_MODELS.each do |model| - if Elasticsearch::Model.client.indices.exists? index: model.index_name + if Elasticsearch::Model.client.indices.exists? index: model.index_name.to_s model.__elasticsearch__.create_index! force: true else model.__elasticsearch__.create_index!