From 00e7ef085f9d7157b2df2c82446f2461e71413a2 Mon Sep 17 00:00:00 2001 From: Rob Kaufman Date: Sun, 2 Jan 2022 22:55:05 -0800 Subject: [PATCH] Settings plus cross search (#1753) * draft of uncompleted implementation of cross tenant search * port settings from hyku_addons, set up settings as properties * email settings and env vars * move many settings to account or env vars, set up gtm * goodbye SETTINGS__ * working on specs * splash view fix * more spec fixes * more spec fixes * more spec fixes * rubocop fixes * fix oai and s3 buckets * always set web_host, fix mailer spec * Typo/Spelling fix * spec typo * dynamic display and edit of settings * Update .env (#1752) * Update .env * Update .env * rubocop * merge concepts of cross search with new settings, rework cross search to be many to many and use the db * rubocop * better solr nil check * add some model & system test for cross tenant search * Deleting a full_tenant from a search failed because '1' is sent back instead of 'true', hence I added typecasting * remove extra end * rubocop * rubocop fixes * make sure rdf doesnt bump to 3.2 as ldp is broken with that version * clean up specs. collection controller is moved to settings, so specs need to go * fix selenium version issue * fix elastic jobs * try to fix catalog spec for ci * mark domain names feature spec pending * trying to make circle ci happy Co-authored-by: edward --- .env | 21 +- Dockerfile | 2 +- Gemfile | 3 +- Gemfile.lock | 291 +++++++++--------- README.md | 4 +- app/assets/javascripts/application.js | 2 + app/assets/javascripts/proprietor.js | 11 + app/controllers/account_sign_up_controller.rb | 2 +- app/controllers/admin/accounts_controller.rb | 4 +- app/controllers/application_controller.rb | 12 +- app/controllers/catalog_controller.rb | 14 +- app/controllers/contacts_controller.rb | 30 -- .../hyku/registrations_controller.rb | 4 +- .../proprietor/accounts_controller.rb | 36 ++- app/helpers/google_tag_manager_helper.rb | 36 +++ app/helpers/hyku_helper.rb | 6 +- .../per_tenant_smtp_interceptor.rb | 2 +- app/jobs/create_account_inline_job.rb | 2 + app/jobs/create_fcrepo_endpoint_job.rb | 2 + app/jobs/create_solr_collection_job.rb | 73 ++++- app/jobs/remove_solr_collection_job.rb | 8 +- app/models/account.rb | 30 +- app/models/account_cross_search.rb | 9 + app/models/concerns/account_cname.rb | 3 +- app/models/concerns/account_settings.rb | 127 +++++++- app/models/hyrax/contact_form.rb | 6 +- app/models/nil_endpoint.rb | 4 + app/models/nil_site.rb | 2 +- app/models/redis_endpoint.rb | 2 +- app/models/solr_endpoint.rb | 6 +- app/services/create_account.rb | 2 + app/views/_head_tag_extras.html.erb | 1 + app/views/admin/accounts/edit.html.erb | 15 +- app/views/contacts/edit.html.erb | 35 --- app/views/devise/shared/_links.html.erb | 2 +- app/views/gtm/_gtm_body.html.erb | 12 + app/views/gtm/_gtm_head.html.erb | 15 + .../dashboard/sidebar/_configuration.html.erb | 80 ++--- .../sidebar/_repository_content.html.erb | 2 +- app/views/layouts/hyrax.html.erb | 1 + .../accounts/_domain_name_fields.html.erb | 6 + ..._full_account_cross_search_fields.html.erb | 4 + app/views/proprietor/accounts/edit.html.erb | 63 ++-- app/views/proprietor/accounts/new.html.erb | 12 + app/views/shared/_settings.html.erb | 8 + app/views/splash/index.html.erb | 2 +- config/application.rb | 14 +- config/environments/development.rb | 3 +- config/environments/production.rb | 10 +- config/initializers/apartment.rb | 2 +- config/initializers/bulkrax.rb | 2 +- config/initializers/carrierwave_config.rb | 19 -- config/initializers/config.rb | 13 - config/initializers/devise.rb | 2 +- config/initializers/hyrax.rb | 42 +-- config/initializers/secure_headers.rb | 2 +- config/locales/en.yml | 19 -- config/locales/simple_form.en.yml | 27 +- config/routes.rb | 5 +- config/settings.yml | 75 ----- config/solr.yml | 3 +- ...920061254_create_account_cross_searches.rb | 10 + ...210920065530_add_search_only_to_account.rb | 5 + db/schema.rb | 14 +- db/seeds.rb | 2 +- docker-compose.override-nodory.yml | 6 +- docker-compose.yml | 3 +- .../better_active_elastic_job_adapter.rb | 14 +- ops/env.conf | 24 -- ops/helm.yaml | 3 - ops/nginx.sh | 28 -- ops/review-deploy.tmpl.yaml | 103 +------ ops/webapp.conf | 16 - .../account_sign_up_controller_spec.rb | 26 +- .../admin/accounts_controller_spec.rb | 2 +- spec/controllers/contacts_controller_spec.rb | 84 ----- .../hyku/registrations_controller_spec.rb | 2 +- spec/features/accounts_spec.rb | 1 + spec/features/admin_dashboard_spec.rb | 1 - spec/features/contact_spec.rb | 23 -- spec/features/splash_spec.rb | 3 + spec/jobs/create_solr_collection_job_spec.rb | 2 +- .../better_active_elastic_job_adapter_spec.rb | 3 +- spec/mailers/hyrax/contact_mailer_spec.rb | 2 + spec/models/account_cross_search_spec.rb | 13 + spec/models/account_spec.rb | 78 ++++- spec/models/hyrax/contact_form_spec.rb | 13 +- spec/models/uploaded_file_spec.rb | 2 +- spec/rails_helper.rb | 18 +- spec/requests/catalog_controller_spec.rb | 74 +++++ spec/routing/contact_routing_spec.rb | 16 - spec/support/matchers.rb | 4 +- spec/support/multitenancy_metadata.rb | 49 +-- .../shared_examples_for_csv_importer.rb | 4 +- spec/system/edit_account_spec.rb | 29 ++ spec/system/new_account_spec.rb | 35 +++ spec/views/splash/index.html.erb_spec.rb | 13 +- 97 files changed, 1073 insertions(+), 904 deletions(-) create mode 100644 app/assets/javascripts/proprietor.js delete mode 100644 app/controllers/contacts_controller.rb create mode 100644 app/helpers/google_tag_manager_helper.rb create mode 100644 app/models/account_cross_search.rb create mode 100644 app/views/_head_tag_extras.html.erb delete mode 100644 app/views/contacts/edit.html.erb create mode 100644 app/views/gtm/_gtm_body.html.erb create mode 100644 app/views/gtm/_gtm_head.html.erb create mode 100644 app/views/proprietor/accounts/_domain_name_fields.html.erb create mode 100644 app/views/proprietor/accounts/_full_account_cross_search_fields.html.erb create mode 100644 app/views/shared/_settings.html.erb delete mode 100644 config/initializers/carrierwave_config.rb delete mode 100644 config/initializers/config.rb delete mode 100644 config/settings.yml create mode 100644 db/migrate/20210920061254_create_account_cross_searches.rb create mode 100644 db/migrate/20210920065530_add_search_only_to_account.rb delete mode 100644 ops/env.conf delete mode 100644 ops/helm.yaml delete mode 100755 ops/nginx.sh delete mode 100644 ops/webapp.conf delete mode 100644 spec/controllers/contacts_controller_spec.rb delete mode 100644 spec/features/contact_spec.rb create mode 100644 spec/models/account_cross_search_spec.rb create mode 100644 spec/requests/catalog_controller_spec.rb delete mode 100644 spec/routing/contact_routing_spec.rb create mode 100644 spec/system/edit_account_spec.rb create mode 100644 spec/system/new_account_spec.rb diff --git a/.env b/.env index 1280ddbf7..1b799e796 100644 --- a/.env +++ b/.env @@ -18,10 +18,8 @@ PASSENGER_APP_ENV=development RAILS_LOG_TO_STDOUT=true REDIS_HOST=redis SECRET_KEY_BASE=asdf -SETTINGS__ACTIVE_JOB__QUEUE_ADAPTER=sidekiq -SETTINGS__BULKRAX__ENABLED=false -SETTINGS__FITS_PATH=/app/fits/fits.sh -SETTINGS__SOLR__URL=http://admin:admin@solr:8983/solr/ +HYRAX_ACTIVE_JOB_QUEUE=sidekiq +HYRAX_FITS_PATH=/app/fits/fits.sh SOLR_ADMIN_PASSWORD=admin SOLR_ADMIN_USER=admin SOLR_COLLECTION_NAME=hydra-development @@ -31,12 +29,11 @@ SOLR_PORT=8983 SOLR_URL=http://admin:admin@solr:8983/solr/ # Comment out these 5 for single tenancy / Uncomment for multi -SETTINGS__MULTITENANCY__ADMIN_HOST=hyku.test -SETTINGS__MULTITENANCY__ADMIN_ONLY_TENANT_CREATION=false -SETTINGS__MULTITENANCY__DEFAULT_HOST=%{tenant}.hyku.test -SETTINGS__MULTITENANCY__ROOT_HOST=hyku.test -SETTINGS__MULTITENANCY__ENABLED=true +HYKU_ADMIN_HOST=hyku.test +HYKU_ADMIN_ONLY_TENANT_CREATION=false +HYKU_DEFAULT_HOST=%{tenant}.hyku.test +HYKU_ROOT_HOST=hyku.test +HYKU_MULTITENANT=true # Comment out these 2 for multi tenancy / Uncomment for single -# SETTINGS__MULTITENANCY__ROOT_HOST=hyku.test -# SETTINGS__MULTITENANCY__ENABLED=false - +# HYKU_ROOT_HOST=hyku.test +# HYKU_MULTITENANT=false diff --git a/Dockerfile b/Dockerfile index ac7c95694..7d95d4273 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,7 +26,7 @@ RUN bundle install --jobs "$(nproc)" COPY --chown=1001:101 $APP_PATH /app/samvera/hyrax-webapp -ARG SETTINGS__BULKRAX__ENABLED="false" +ARG HYKU_BULKRAX_ENABLED="false" RUN RAILS_ENV=production SECRET_KEY_BASE=`bin/rake secret` DB_ADAPTER=nulldb DATABASE_URL='postgresql://fake' bundle exec rake assets:precompile FROM hyku-base as hyku-worker diff --git a/Gemfile b/Gemfile index 99d5b3a98..18dc4e908 100644 --- a/Gemfile +++ b/Gemfile @@ -105,7 +105,6 @@ gem 'devise-i18n' gem 'devise_invitable', '~> 1.6' gem 'apartment' -gem 'config', '>= 2.2.1', '< 4.0' gem 'is_it_working' gem 'rolify' @@ -124,8 +123,10 @@ group :aws do end gem 'bootstrap-datepicker-rails' +gem "cocoon" gem 'codemirror-rails' gem 'parser', '~> 2.5.3' +gem 'rdf', '~> 3.1.15' # rdf 3.2.0 removed SerializedTransaction which ldp requires gem 'riiif', '~> 1.1' gem 'secure_headers' gem 'sidekiq' diff --git a/Gemfile.lock b/Gemfile.lock index ac725c91a..5e46d332f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,10 +9,10 @@ GIT GIT remote: https://github.com/samvera-labs/bulkrax.git - revision: e6e68cf98bbbe5eb95391f23d8f9801f2cdbefce + revision: 687f2488abfd619d506873792f38f346056a6c77 branch: main specs: - bulkrax (1.0.1) + bulkrax (1.0.2) bagit (~> 0.4) coderay iso8601 (~> 0.9.0) @@ -60,7 +60,7 @@ GEM erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - active-fedora (12.1.1) + active-fedora (12.2.3) active-triples (>= 0.11.0, < 2.0.0) activemodel (>= 4.2.10, < 5.3) activesupport (>= 4.2.4, < 5.3) @@ -68,15 +68,15 @@ GEM faraday (~> 0.12) faraday-encoding (= 0.0.4) ldp (>= 0.7.0, < 2) + rdf-vocab (< 3.1.5) rsolr (>= 1.1.2, < 3) ruby-progressbar (~> 1.0) - solrizer (>= 3.4, < 5) active-triples (1.1.1) activemodel (>= 3.0.0) activesupport (>= 3.0.0) rdf (>= 2.0.2, < 4.0) rdf-vocab (>= 2.0, < 4.0) - active_encode (0.8.1) + active_encode (0.8.2) rails sprockets (< 4) activejob (5.2.6) @@ -92,10 +92,10 @@ GEM activemodel (= 5.2.6) activesupport (= 5.2.6) arel (>= 9.0) - activerecord-import (1.2.0) - activerecord (>= 3.2) - activerecord-nulldb-adapter (0.4.0) - activerecord (>= 2.0.0) + activerecord-import (1.3.0) + activerecord (>= 4.2) + activerecord-nulldb-adapter (0.8.0) + activerecord (>= 5.2.0, < 7.1) activestorage (5.2.6) actionpack (= 5.2.6) activerecord (= 5.2.6) @@ -109,34 +109,34 @@ GEM public_suffix (>= 2.0.2, < 5.0) almond-rails (0.3.0) rails (>= 4.2) - amazing_print (1.3.0) + amazing_print (1.4.0) apartment (2.2.1) activerecord (>= 3.1.2, < 6.0) parallel (>= 0.7.1) public_suffix (>= 2) rack (>= 1.3.6) arel (9.0.0) - ast (2.4.1) - autoprefixer-rails (10.3.3.0) + ast (2.4.2) + autoprefixer-rails (10.4.0.0) execjs (~> 2) awesome_nested_set (3.4.0) activerecord (>= 4.0.0, < 7.0) aws-eventstream (1.2.0) - aws-partitions (1.496.0) - aws-sdk-core (3.121.0) + aws-partitions (1.543.0) + aws-sdk-core (3.125.0) aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.239.0) + aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-kms (1.48.0) - aws-sdk-core (~> 3, >= 3.120.0) + aws-sdk-kms (1.53.0) + aws-sdk-core (~> 3, >= 3.125.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.102.0) - aws-sdk-core (~> 3, >= 3.120.0) + aws-sdk-s3 (1.110.0) + aws-sdk-core (~> 3, >= 3.125.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) - aws-sdk-sqs (1.29.0) - aws-sdk-core (~> 3, >= 3.99.0) + aws-sdk-sqs (1.49.0) + aws-sdk-core (~> 3, >= 3.125.0) aws-sigv4 (~> 1.1) aws-sigv4 (1.4.0) aws-eventstream (~> 1, >= 1.0.2) @@ -149,7 +149,7 @@ GEM validatable (~> 1.6) bcp47 (0.3.3) i18n - bcrypt (3.1.13) + bcrypt (3.1.16) benchmark_methods (0.7) bibtex-ruby (6.0.0) latex-decode (~> 0.0) @@ -221,13 +221,14 @@ GEM builder (3.2.4) byebug (11.1.3) cancancan (1.17.0) - capybara (3.33.0) + capybara (3.36.0) addressable + matrix mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) - regexp_parser (~> 1.5) + regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) capybara-screenshot (1.0.25) capybara (>= 1.0, < 4) @@ -240,13 +241,14 @@ GEM carrierwave-aws (1.4.0) aws-sdk-s3 (~> 1.0) carrierwave (>= 0.7, < 2.1) - childprocess (3.0.0) + childprocess (4.1.0) citeproc (1.0.10) namae (~> 1.0) citeproc-ruby (1.1.14) citeproc (~> 1.0, >= 1.0.9) csl (~> 1.6) clipboard-rails (1.7.1) + cocoon (1.2.15) codemirror-rails (5.16.0) railties (>= 3.0, < 6.0) coderay (1.1.3) @@ -259,38 +261,39 @@ GEM coffee-script-source (1.12.2) colorize (0.8.1) concurrent-ruby (1.1.9) - config (3.1.0) - deep_merge (~> 1.2, >= 1.2.1) - dry-validation (~> 1.0, >= 1.0.0) connection_pool (2.2.5) - crack (0.4.3) - safe_yaml (~> 1.0.0) + 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) - database_cleaner (1.8.5) + database_cleaner (2.0.1) + database_cleaner-active_record (~> 2.0.0) + database_cleaner-active_record (2.0.1) + activerecord (>= 5.a) + database_cleaner-core (~> 2.0.0) + database_cleaner-core (2.0.1) declarative (0.0.20) - deep_merge (1.2.1) deprecation (1.1.0) activesupport - devise (4.7.2) + devise (4.8.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) - devise-guests (0.7.0) + devise-guests (0.8.1) devise - devise-i18n (1.9.1) - devise (>= 4.7.1) + devise-i18n (1.10.1) + devise (>= 4.8.0) devise_invitable (1.7.5) actionmailer (>= 4.1.0) devise (>= 4.0.0) - diff-lcs (1.4.2) - docile (1.3.2) + diff-lcs (1.5.0) + docile (1.4.0) docopt (0.5.0) draper (4.0.2) actionpack (>= 5.0) @@ -302,12 +305,12 @@ GEM dropbox_api (0.1.18) faraday (<= 1.0) oauth2 (~> 1.1) - dry-configurable (0.12.1) + dry-configurable (0.13.0) concurrent-ruby (~> 1.0) - dry-core (~> 0.5, >= 0.5.0) - dry-container (0.8.0) + dry-core (~> 0.6) + dry-container (0.9.0) concurrent-ruby (~> 1.0) - dry-configurable (~> 0.1, >= 0.1.3) + dry-configurable (~> 0.13, >= 0.13.0) dry-core (0.7.1) concurrent-ruby (~> 1.0) dry-equalizer (0.3.0) @@ -324,9 +327,9 @@ GEM dry-monads (1.4.0) concurrent-ruby (~> 1.0) dry-core (~> 0.7) - dry-schema (1.7.1) + dry-schema (1.8.0) concurrent-ruby (~> 1.0) - dry-configurable (~> 0.8, >= 0.8.3) + dry-configurable (~> 0.13, >= 0.13.0) dry-core (~> 0.5, >= 0.5) dry-initializer (~> 3.0) dry-logic (~> 1.0) @@ -346,13 +349,12 @@ GEM dry-core (~> 0.5, >= 0.5) dry-inflector (~> 0.1, >= 0.1.2) dry-logic (~> 1.0, >= 1.0.2) - dry-validation (1.6.0) + dry-validation (1.7.0) concurrent-ruby (~> 1.0) dry-container (~> 0.7, >= 0.7.1) - dry-core (~> 0.4) - dry-equalizer (~> 0.2) + dry-core (~> 0.5, >= 0.5) dry-initializer (~> 3.0) - dry-schema (~> 1.5, >= 1.5.2) + dry-schema (~> 1.8, >= 1.8.0) easy_translate (0.5.1) thread thread_safe @@ -368,14 +370,14 @@ GEM equivalent-xml (0.6.0) nokogiri (>= 1.4.3) erubi (1.10.0) - ethon (0.14.0) + ethon (0.15.0) ffi (>= 1.15.0) excon (0.71.1) execjs (2.8.1) - factory_bot (6.0.2) + factory_bot (6.2.0) activesupport (>= 5.0.0) - factory_bot_rails (6.0.0) - factory_bot (~> 6.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) railties (>= 5.0.0) faraday (0.17.4) multipart-post (>= 1.2, < 3) @@ -391,13 +393,13 @@ GEM flot-rails (0.0.7) jquery-rails flutie (2.2.0) - font-awesome-rails (4.7.0.7) - railties (>= 3.2, < 7) + font-awesome-rails (4.7.0.8) + railties (>= 3.2, < 8.0) gems (1.2.0) gender_detector (0.1.2) unicode_utils (>= 1.3.0) - geocoder (1.6.7) - globalid (0.5.2) + geocoder (1.7.1) + globalid (1.0.0) activesupport (>= 5.0) google-api-client (0.53.0) google-apis-core (~> 0.1) @@ -411,9 +413,9 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-discovery_v1 (0.6.0) + google-apis-discovery_v1 (0.7.0) google-apis-core (>= 0.4, < 2.a) - google-apis-drive_v3 (0.13.0) + google-apis-drive_v3 (0.16.0) google-apis-core (>= 0.4, < 2.a) google-apis-generator (0.4.0) activesupport (>= 5.0) @@ -421,7 +423,7 @@ GEM google-apis-core (>= 0.4, < 2.a) google-apis-discovery_v1 (~> 0.5) thor (>= 0.20, < 2.a) - google-apis-sheets_v4 (0.9.0) + google-apis-sheets_v4 (0.10.0) google-apis-core (>= 0.4, < 2.a) google_drive (3.0.7) google-apis-drive_v3 (>= 0.5.0, < 1.0.0) @@ -444,7 +446,7 @@ GEM highline (2.0.3) hiredis (0.6.3) htmlentities (4.3.4) - http_logger (0.6.0) + http_logger (0.7.0) httpclient (2.8.3) hydra-access-controls (11.0.7) active-fedora (>= 10.0.0) @@ -456,10 +458,10 @@ GEM hydra-core (11.0.7) hydra-access-controls (= 11.0.7) railties (>= 4.0.0, < 6) - hydra-derivatives (3.5.0) - active-fedora (>= 11.3.1, < 14) + hydra-derivatives (3.6.0) + active-fedora (>= 11.5.6, != 13.2.1, != 13.2.0, != 13.1.3, != 13.1.2, != 13.1.1, != 13.1.0, != 13.0.0, != 12.2.1, != 12.2.0, != 12.1.1, != 12.1.0, != 12.0.3, != 12.0.2, != 12.0.1, != 12.0.0) active_encode (~> 0.1) - activesupport (>= 4.0, < 6) + activesupport (>= 4.0, < 7) addressable (~> 2.5) deprecation mime-types (> 2.0, < 4.0) @@ -487,8 +489,8 @@ GEM hydra-derivatives (~> 3.0) hydra-file_characterization (~> 1.0) hydra-pcdm (>= 0.9) - hyrax (2.9.5) - active-fedora (>= 11.5.2, < 12.2) + hyrax (2.9.6) + active-fedora (>= 11.5.2, < 13) almond-rails (~> 0.1) awesome_nested_set (~> 3.1) blacklight (~> 6.14) @@ -542,11 +544,11 @@ GEM bolognese (~> 1.8, >= 1.8.6) hyrax (~> 2.9) rails (~> 5.2.4, >= 5.2.4.3) - i18n (1.8.10) + i18n (1.8.11) concurrent-ruby (~> 1.0) i18n-debug (1.2.0) i18n (< 2) - i18n-tasks (0.9.31) + i18n-tasks (0.9.37) activesupport (>= 4.0.2) ast (>= 2.1.0) erubi @@ -562,7 +564,8 @@ GEM is_it_working (1.1.0) iso-639 (0.3.5) iso8601 (0.9.1) - jbuilder (2.11.2) + jbuilder (2.11.5) + actionview (>= 5.0.0) activesupport (>= 5.0.0) jmespath (1.4.0) jquery-datatables-rails (3.4.0) @@ -576,9 +579,9 @@ GEM thor (>= 0.14, < 2.0) jquery-ui-rails (6.0.1) railties (>= 3.2.16) - json (2.5.1) - json-canonicalization (0.2.1) - json-ld (3.1.9) + json (2.6.1) + json-canonicalization (0.3.0) + json-ld (3.1.10) htmlentities (~> 4.3) json-canonicalization (~> 0.2) link_header (~> 0.0, >= 0.0.8) @@ -593,19 +596,19 @@ GEM jsonlint (0.3.0) oj (~> 3) optimist (~> 3) - jwt (2.2.3) - kaminari (1.2.1) + jwt (2.3.0) + 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) + kaminari-core (= 1.2.2) + kaminari-core (1.2.2) kaminari_route_prefix (0.1.1) kaminari (~> 1.0) language_list (1.2.1) @@ -666,13 +669,13 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) - logger (1.4.3) + logger (1.5.0) lograge (0.11.2) actionpack (>= 4) activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.12.0) + loofah (2.13.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -680,8 +683,8 @@ GEM mailboxer (0.15.1) carrierwave (>= 0.5.8) rails (>= 5.0.0) - marcel (1.0.1) - maremma (4.9.5) + marcel (1.0.2) + maremma (4.9.6) activesupport (>= 4.2.5) addressable (>= 2.3.6) builder (~> 3.2, >= 3.2.2) @@ -692,15 +695,16 @@ GEM nokogiri (~> 1.11.2) oj (>= 2.8.3) oj_mimic_json (~> 1.0, >= 1.0.1) + matrix (0.4.2) memoist (0.16.2) method_source (1.0.0) - mime-types (3.3.1) + mime-types (3.4.1) mime-types-data (~> 3.2015) - mime-types-data (3.2021.0901) + mime-types-data (3.2021.1115) mini_magick (4.11.0) - mini_mime (1.1.1) + mini_mime (1.1.2) mini_portile2 (2.5.3) - minitest (5.14.4) + minitest (5.15.0) mods (2.4.1) edtf iso-639 @@ -732,21 +736,21 @@ GEM builder (>= 3.1.0) faraday faraday_middleware - oauth (0.5.6) + oauth (0.5.8) oauth2 (1.4.7) faraday (>= 0.8, < 2.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - oj (3.13.4) + oj (3.13.10) oj_mimic_json (1.0.1) openseadragon (0.6.0) rails (> 3.2.0) optimist (3.0.1) orm_adapter (0.5.0) - os (1.1.1) - parallel (1.19.2) + os (1.1.4) + parallel (1.21.0) parser (2.5.3.0) ast (~> 2.4.0) parslet (2.0.0) @@ -757,12 +761,12 @@ GEM nokogiri (>= 1.8.0) public_suffix (>= 2.0.0, < 2.1) power_converter (0.1.2) - powerpack (0.1.2) + powerpack (0.1.3) public_suffix (2.0.5) pul_uv_rails (2.0.1) - puma (4.3.9) + puma (4.3.10) nio4r (~> 2.0) - qa (5.6.0) + qa (5.7.0) activerecord-import deprecation faraday @@ -771,7 +775,7 @@ GEM nokogiri (~> 1.6) rails (>= 5.0, < 6.2) rdf - racc (1.5.2) + racc (1.6.0) rack (2.2.3) rack-test (0.7.0) rack (>= 1.0, < 3) @@ -872,12 +876,12 @@ GEM rexml (~> 3.2) redic (1.5.3) hiredis - redis (4.4.0) + redis (4.5.1) redis-namespace (1.8.1) redis (>= 3.0.4) - redlock (1.2.1) + redlock (1.2.2) redis (>= 3.0.0, < 5.0) - regexp_parser (1.7.1) + regexp_parser (2.2.0) representable (3.1.1) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) @@ -892,40 +896,40 @@ GEM riiif (1.7.1) deprecation (>= 1.0.0) railties (>= 4.2, < 6) - rolify (5.3.0) - rsolr (2.3.0) + rolify (6.0.0) + rsolr (2.4.0) builder (>= 2.1.2) faraday (>= 0.9.0) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) rspec-activemodel-mocks (1.1.0) activemodel (>= 3.0) activesupport (>= 3.0) rspec-mocks (>= 2.99, < 4.0) - rspec-core (3.9.2) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) + rspec-support (~> 3.10.0) rspec-its (1.3.0) rspec-core (>= 3.0.0) rspec-expectations (>= 3.0.0) - rspec-mocks (3.9.1) + rspec-mocks (3.10.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-rails (4.0.1) - actionpack (>= 4.2) - activesupport (>= 4.2) - railties (>= 4.2) - rspec-core (~> 3.9) - rspec-expectations (~> 3.9) - rspec-mocks (~> 3.9) - rspec-support (~> 3.9) + rspec-support (~> 3.10.0) + rspec-rails (5.0.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) rspec-retry (0.6.2) rspec-core (> 3.3) - rspec-support (3.9.3) + rspec-support (3.10.3) rspec_junit_formatter (0.4.1) rspec-core (>= 2, < 4, != 2.12.0) rubocop (0.52.1) @@ -945,8 +949,7 @@ GEM ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) ruby_dep (1.5.0) - rubyzip (2.3.0) - safe_yaml (1.0.5) + rubyzip (2.3.2) samvera-nesting_indexer (2.0.0) dry-equalizer sass (3.7.4) @@ -965,12 +968,13 @@ GEM scanf (1.0.0) scss_lint (0.59.0) sass (~> 3.5, >= 3.5.5) - secure_headers (6.3.0) + secure_headers (6.3.3) select2-rails (3.5.11) selenium-webdriver (3.142.7) childprocess (>= 0.5, < 4.0) + rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) - shex (0.6.3) + shex (0.6.4) ebnf (~> 2.1, >= 2.2) htmlentities (~> 4.3) json-ld (~> 3.1) @@ -981,7 +985,7 @@ GEM sxp (~> 1.1) shoulda-matchers (4.5.1) activesupport (>= 4.2.0) - sidekiq (6.2.1) + sidekiq (6.3.1) connection_pool (>= 2.2.2) rack (~> 2.0) redis (>= 4.2.0) @@ -993,11 +997,12 @@ GEM simple_form (5.1.0) actionpack (>= 5.2) activemodel (>= 5.2) - simplecov (0.16.1) + simplecov (0.21.2) docile (~> 1.1) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.3) slop (4.9.1) solr_wrapper (2.2.0) faraday @@ -1031,16 +1036,16 @@ GEM babel-source (>= 5.8.11) babel-transpiler sprockets (>= 3.0.0) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) ssrf_filter (1.0.7) sxp (1.1.0) rdf (~> 3.1) temple (0.8.2) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) tether-rails (1.4.0) rails (>= 3.1) thor (1.1.0) @@ -1049,7 +1054,7 @@ GEM tilt (2.0.10) tinymce-rails (4.9.11) railties (>= 3.1.1) - trailblazer-option (0.1.1) + trailblazer-option (0.1.2) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) @@ -1064,12 +1069,12 @@ GEM uber (0.1.0) uglifier (4.2.0) execjs (>= 0.3.0, < 3) - unicode-display_width (1.7.0) - unicode-types (1.6.0) + unicode-display_width (1.8.0) + unicode-types (1.7.0) unicode_utils (1.4.0) validatable (1.6.7) - warden (1.2.8) - rack (>= 2.0.6) + warden (1.2.9) + rack (>= 2.0.9) web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) @@ -1087,7 +1092,8 @@ GEM websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - xml-simple (1.1.8) + xml-simple (1.1.9) + rexml xpath (3.2.0) nokogiri (~> 1.8) @@ -1108,9 +1114,9 @@ DEPENDENCIES capybara capybara-screenshot (~> 1.0) carrierwave-aws (~> 1.3) + cocoon codemirror-rails coffee-rails (~> 4.2) - config (>= 2.2.1, < 4.0) database_cleaner devise devise-guests (~> 0.3) @@ -1138,6 +1144,7 @@ DEPENDENCIES rack-test (= 0.7.0) rails (~> 5.2.5) rails-controller-testing + rdf (~> 3.1.15) riiif (~> 1.1) rolify rsolr (~> 2.0) diff --git a/README.md b/README.md index 6f8016c1f..bc91d665e 100644 --- a/README.md +++ b/README.md @@ -125,9 +125,9 @@ Hyku relies on the helm charts provided by Hyrax. See [Deployment Info](https:// Much of the default configuration in Hyku is set up to use multi-tenant mode. This default mode allows Hyku users to run the equivielent of multiple Hyrax installs on a single set of resources. However, sometimes the subdomain splitting multi-headed complexity is simply not needed. If this is the case, then single tenant mode is for you. Single tenant mode will not show the tenant sign up page, or any of the tenant management screens. Instead it shows a single Samvera instance at what ever domain is pointed at the application. -To enable single tenant, in your settings.yml file change multitenancy/enabled to `false` or set `SETTINGS__MULTITENANCY__ENABLED=false` in your `docker-compose.yml` and `docker-compose.production.yml` configs. After changinig this setting, run `rails db:seed` to prepopulate the single tenant. +To enable single tenant, set `HYKU_MULTITENANT=false` in your `docker-compose.yml` and `docker-compose.production.yml` configs. After changinig this setting, run `rails db:seed` to prepopulate the single tenant. -In single tenant mode, both the application root (eg. localhost, or hyku.test) and the tenant url single.* (eg. single.hyku.test) will load the tenant. Override the root host by setting multitenancy/root_host in settings.yml or `SETTINGS__MULTITENANCY__ROOT_HOST`. +In single tenant mode, both the application root (eg. localhost, or hyku.test) and the tenant url single.* (eg. single.hyku.test) will load the tenant. Override the root host by setting HYKU_ROOT_HOST`. To change from single- to multi-tenant mode, change the multitenancy/enabled flag to true and restart the application. Change the 'single' tenant account cname in the Accounts edit interface to the correct hostname. diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index df5702c12..d77a92139 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -20,6 +20,7 @@ //= require dataTables/bootstrap/3/jquery.dataTables.bootstrap //= require stat_slider //= require turbolinks +//= require cocoon //= require tether // Required by Blacklight @@ -35,6 +36,7 @@ //= require hyku/admin/appearance/themes //= require hyku/groups/per_page //= require hyku/groups/add_member +//= require proprietor //= require bootstrap_carousel //= require bootstrap-datepicker diff --git a/app/assets/javascripts/proprietor.js b/app/assets/javascripts/proprietor.js new file mode 100644 index 000000000..5e16c6e20 --- /dev/null +++ b/app/assets/javascripts/proprietor.js @@ -0,0 +1,11 @@ +Blacklight.onLoad(function() { + if($('#account_search_only').length > 0) { + $('#account_search_only').change(function() { + if(this.checked) { + $('#full_account_cross_container').removeClass('hide') + } else { + $('#full_account_cross_container').addClass('hide') + } + }) + } +}) diff --git a/app/controllers/account_sign_up_controller.rb b/app/controllers/account_sign_up_controller.rb index 41c653886..89b06cb6e 100644 --- a/app/controllers/account_sign_up_controller.rb +++ b/app/controllers/account_sign_up_controller.rb @@ -33,7 +33,7 @@ def ensure_admin! end def admin_only_tenant_creation? - Settings.multitenancy.admin_only_tenant_creation + ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_ADMIN_ONLY_TENANT_CREATION', false)) end def first_user_registration_url diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb index adeebe577..f27c0e2a7 100644 --- a/app/controllers/admin/accounts_controller.rb +++ b/app/controllers/admin/accounts_controller.rb @@ -17,7 +17,7 @@ def edit def update respond_to do |format| if @account.update(account_params) - format.html { redirect_to edit_admin_account_path, notice: 'Account was successfully updated.' } + format.html { redirect_to edit_admin_account_path(@account), notice: 'Account was successfully updated.' } format.json { render :show, status: :ok, location: root_url } else format.html { render :edit } @@ -29,7 +29,7 @@ def update private def account_params - params.require(:account).permit(:name, :cname, :title) + params.require(:account).permit(:name, :cname, :title, *@account.public_settings.keys) end def set_current_account diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c307b61c0..9449da3c0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -68,7 +68,7 @@ def super_and_current_users private def require_active_account! - return unless Settings.multitenancy.enabled + return if singletenant? return if devise_controller? raise Apartment::TenantNotFound, "No tenant for #{request.host}" unless current_account.persisted? end @@ -78,11 +78,11 @@ def set_account_specific_connections! end def multitenant? - Settings.multitenancy.enabled + @multitenant ||= ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_MULTITENANT', false)) end def singletenant? - !Settings.multitenancy.enabled + !multitenant? end def elevate_single_tenant! @@ -94,13 +94,13 @@ def root_host? end def admin_host? - return false unless multitenant? + return false if singletenant? Account.canonical_cname(request.host) == Account.admin_host end def current_account @current_account ||= Account.from_request(request) - @current_account ||= if Settings.multitenancy.enabled + @current_account ||= if multitenant? Account.new do |a| a.build_solr_endpoint a.build_fcrepo_endpoint @@ -133,6 +133,6 @@ def append_info_to_payload(payload) end def ssl_configured? - ActiveRecord::Type::Boolean.new.cast(Settings.ssl_configured) + ActiveRecord::Type::Boolean.new.cast(current_account.ssl_configured) end end diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index f5a2fdbb9..71986633b 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -339,21 +339,23 @@ def self.modified_field config.add_sort_field "#{modified_field} desc", label: "date modified \u25BC" config.add_sort_field "#{modified_field} asc", label: "date modified \u25B2" + # OAI Config fields config.oai = { provider: { - repository_name: Settings.oai.name, - repository_url: Settings.oai.url, - record_prefix: Settings.oai.prefix, - admin_email: Settings.oai.email, - sample_id: Settings.oai.sample_id + repository_name: ->(controller) { controller.send(:current_account)&.name.presence }, + # repository_url: ->(controller) { controller.oai_catalog_url }, + record_prefix: ->(controller) { controller.send(:current_account).oai_prefix }, + admin_email: ->(controller) { controller.send(:current_account).oai_admin_email }, + sample_id: ->(controller) { controller.send(:current_account).oai_sample_identifier } }, document: { - limit: 25, # number of records returned with each request, default: 15 + limit: 100, # number of records returned with each request, default: 15 set_fields: [ # ability to define ListSets, optional, default: nil { label: 'collection', solr_field: 'isPartOf_ssim' } ] } } + # If there are more than this many search results, no spelling ("did you # mean") suggestion is offered. config.spell_max = 5 diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb deleted file mode 100644 index 099bf78d7..000000000 --- a/app/controllers/contacts_controller.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -class ContactsController < SitesController - # GET /sites/1/edit - def edit - add_breadcrumb t(:'hyrax.controls.home'), root_path - add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path - add_breadcrumb t(:'hyrax.admin.sidebar.configuration'), '#' - add_breadcrumb t(:'hyrax.admin.sidebar.contact'), edit_site_contact_path - end - - # PATCH/PUT /sites/1 - # PATCH/PUT /sites/1.json - def update - respond_to do |format| - if @site.update(site_params) - format.html { redirect_to edit_site_contact_path, notice: 'Contact page was successfully updated.' } - else - format.html { render :edit } - end - end - end - - private - - # Never trust parameters from the scary internet, only allow the white list through. - def site_params - params.require(:site).permit(:contact_email) - end -end diff --git a/app/controllers/hyku/registrations_controller.rb b/app/controllers/hyku/registrations_controller.rb index af415bcec..fe9a9422a 100644 --- a/app/controllers/hyku/registrations_controller.rb +++ b/app/controllers/hyku/registrations_controller.rb @@ -4,12 +4,12 @@ module Hyku class RegistrationsController < Devise::RegistrationsController before_action :configure_permitted_parameters def new - return super if Settings.devise.account_signup + return super if current_account&.allow_signup redirect_to root_path, alert: t(:'hyku.account.signup_disabled') end def create - return super if Settings.devise.account_signup + return super if current_account&.allow_signup redirect_to root_path, alert: t(:'hyku.account.signup_disabled') end diff --git a/app/controllers/proprietor/accounts_controller.rb b/app/controllers/proprietor/accounts_controller.rb index 6c7010398..8c25d6fbc 100644 --- a/app/controllers/proprietor/accounts_controller.rb +++ b/app/controllers/proprietor/accounts_controller.rb @@ -55,7 +55,10 @@ def create # PATCH/PUT /accounts/1.json def update respond_to do |format| - if @account.update(account_params) + if @account.update(edit_account_params) + f = edit_account_params['full_account_cross_searches_attributes'].to_h + CreateSolrCollectionJob.perform_now(@account) if deleted_or_new(f) + format.html { redirect_to [:proprietor, @account], notice: 'Account was successfully updated.' } format.json { render :show, status: :ok, location: [:proprietor, @account] } else @@ -83,11 +86,36 @@ def ensure_admin! end # Never trust parameters from the scary internet, only allow the permitted parameters through. - def account_params - params.require(:account).permit(:name, :cname, :title, :is_public, + def edit_account_params + params.require(:account).permit(:name, + :cname, + :title, + :is_public, + :search_only, + *@account.live_settings.keys, admin_emails: [], + full_account_cross_searches_attributes: [:id, + :_destroy, + :full_account_id, + full_account_attributes: [:id]], solr_endpoint_attributes: %i[id url], - fcrepo_endpoint_attributes: %i[id url base_path]) + fcrepo_endpoint_attributes: %i[id url base_path], + datacite_endpoint_attributes: %i[mode prefix username password]) + end + + def account_params + params.require(:account).permit( + :name, + :search_only, + admin_emails: [], + full_account_cross_searches_attributes: [:id, :_destroy, :full_account_id, full_account_attributes: [:id]] + ) + end + + def deleted_or_new(hash) + hash.detect do |_k, v| + ActiveModel::Type::Boolean.new.cast(v["_destroy"]) == true || v["id"].blank? + end end end end diff --git a/app/helpers/google_tag_manager_helper.rb b/app/helpers/google_tag_manager_helper.rb new file mode 100644 index 000000000..6a9f6f70c --- /dev/null +++ b/app/helpers/google_tag_manager_helper.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module GoogleTagManagerHelper + def render_gtm_head(_host) + return '' if current_account.gtm_id.blank? + + # rubocop:disable Rails/OutputSafety + <<-HTML.strip_heredoc.html_safe + + + + HTML + # rubocop:enable Rails/OutputSafety + end + + def render_gtm_body(_host) + # render 'layouts/google/gtm_body' + return '' if current_account.gtm_id.blank? + # rubocop:disable Rails/OutputSafety + <<-HTML.strip_heredoc.html_safe + + + + + + HTML + # rubocop:enable Rails/OutputSafety + end +end diff --git a/app/helpers/hyku_helper.rb b/app/helpers/hyku_helper.rb index cc27f9fe8..c33acd741 100644 --- a/app/helpers/hyku_helper.rb +++ b/app/helpers/hyku_helper.rb @@ -2,7 +2,7 @@ module HykuHelper def multitenant? - Settings.multitenancy.enabled + ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_MULTITENANT', false)) end def current_account @@ -15,4 +15,8 @@ def admin_host? Account.canonical_cname(request.host) == Account.admin_host end + + def admin_only_tenant_creation? + ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_ADMIN_ONLY_TENANT_CREATION', false)) + end end diff --git a/app/intercepter/per_tenant_smtp_interceptor.rb b/app/intercepter/per_tenant_smtp_interceptor.rb index 011c12705..51dee3967 100644 --- a/app/intercepter/per_tenant_smtp_interceptor.rb +++ b/app/intercepter/per_tenant_smtp_interceptor.rb @@ -7,7 +7,7 @@ def self.available_smtp_fields def self.delivering_email(message) Account.find_by(tenant: Apartment::Tenant.current)&.switch! - return if (mailer_settings = Settings.smtp_settings).blank? + return if (mailer_settings = Site.instance.account.smtp_settings).blank? if (from = mailer_settings.from).present? message.from = from diff --git a/app/jobs/create_account_inline_job.rb b/app/jobs/create_account_inline_job.rb index 0def3a1ef..bb4f91aa6 100644 --- a/app/jobs/create_account_inline_job.rb +++ b/app/jobs/create_account_inline_job.rb @@ -7,6 +7,8 @@ def perform(account) CreateSolrCollectionJob.perform_now(account) CreateFcrepoEndpointJob.perform_now(account) CreateRedisNamespaceJob.perform_now(account) + account.create_data_cite_endpoint + # CreateDefaultAdminSetJob.perform_now(account) # handled in Apartment callback end end diff --git a/app/jobs/create_fcrepo_endpoint_job.rb b/app/jobs/create_fcrepo_endpoint_job.rb index cb6058bdf..4b2d3af1d 100644 --- a/app/jobs/create_fcrepo_endpoint_job.rb +++ b/app/jobs/create_fcrepo_endpoint_job.rb @@ -4,6 +4,8 @@ class CreateFcrepoEndpointJob < ApplicationJob non_tenant_job def perform(account) + return NilFcrepoEndpoint.new if account.search_only? + name = account.tenant.parameterize account.create_fcrepo_endpoint(base_path: "/#{name}") diff --git a/app/jobs/create_solr_collection_job.rb b/app/jobs/create_solr_collection_job.rb index 7b44cf45a..35b1726ba 100644 --- a/app/jobs/create_solr_collection_job.rb +++ b/app/jobs/create_solr_collection_job.rb @@ -4,23 +4,29 @@ class CreateSolrCollectionJob < ApplicationJob non_tenant_job + attr_accessor :account ## # @param [Account] def perform(account) + @account = account name = account.tenant.parameterize - unless collection_exists? name - client.get '/solr/admin/collections', params: collection_options.merge(action: 'CREATE', - name: name) + if account.search_only? + perform_for_cross_search_tenant(account, name) + else + perform_for_normal_tenant(account, name) end - - account.create_solr_endpoint(url: collection_url(name), collection: name) end - def without_account(name) + def without_account(name, tenant_list = '') return if collection_exists?(name) - client.get '/solr/admin/collections', params: collection_options.merge(action: 'CREATE', - name: name) + if tenant_list.present? + client.get '/solr/admin/collections', params: collection_options.merge(action: 'CREATEALIAS', + name: name, collections: tenant_list) + else + client.get '/solr/admin/collections', params: collection_options.merge(action: 'CREATE', + name: name) + end end # Transform settings from nested, snaked-cased options to flattened, camel-cased options @@ -67,7 +73,7 @@ def client end def collection_options - CollectionOptions.new(Settings.solr.collection_options.to_hash).to_h + CollectionOptions.new(account ? account.solr_collection_options : Account.solr_collection_options).to_h end def collection_exists?(name) @@ -78,14 +84,49 @@ def collection_exists?(name) end def collection_url(name) - normalized_uri = if Settings.solr.url.ends_with?('/') - Settings.solr.url - else - "#{Settings.solr.url}/" - end - - uri = URI(normalized_uri) + name + uri = URI(solr_url) + name uri.to_s end + + def solr_url + @solr_url ||= ENV['SOLR_URL'] || solr_url_parts + @solr_url = @solr_url.ends_with?('/') ? @solr_url : "#{@solr_url}/" + end + + def solr_url_parts + "http://#{ENV.fetch('SOLR_ADMIN_USER', 'admin')}:#{ENV.fetch('SOLR_ADMIN_PASSWORD', 'admin')}" \ + "@#{ENV.fetch('SOLR_HOST', 'solr')}:#{ENV.fetch('SOLR_PORT', '8983')}/solr/" + end + + def add_solr_endpoint_to_account(account, name) + account.create_solr_endpoint(url: collection_url(name), collection: name) + end + + def perform_for_normal_tenant(account, name) + unless collection_exists? name + client.get '/solr/admin/collections', params: collection_options.merge(action: 'CREATE', + name: name) + end + add_solr_endpoint_to_account(account, name) + end + + def perform_for_cross_search_tenant(account, name) + return if account.full_accounts.blank? + if account.saved_changes&.[]('created_at').present? || account.solr_endpoint.is_a?(NilSolrEndpoint) + create_shared_search_collection(account.full_accounts.map(&:tenant).uniq, name) + account.create_solr_endpoint(url: collection_url(name), collection: name) + else + solr_options = account.solr_endpoint.connection_options.dup + RemoveSolrCollectionJob.perform_now(name, solr_options, 'cross_search_tenant') + create_shared_search_collection(account.full_accounts.map(&:tenant).uniq, name) + account.solr_endpoint.update(url: collection_url(name), collection: name) + end + end + + def create_shared_search_collection(tenant_list, name) + return true if collection_exists?(name) + client.get '/solr/admin/collections', params: collection_options.merge(action: 'CREATEALIAS', + name: name, collections: tenant_list) + end end diff --git a/app/jobs/remove_solr_collection_job.rb b/app/jobs/remove_solr_collection_job.rb index 1d9a493a8..a93eebeb9 100644 --- a/app/jobs/remove_solr_collection_job.rb +++ b/app/jobs/remove_solr_collection_job.rb @@ -5,8 +5,12 @@ class RemoveSolrCollectionJob < ApplicationJob # @param connection_options [Hash] options for connecting to solr. # @option connection_options [String] :url # @option connection_options [String] :url - def perform(collection, connection_options) - solr_client(connection_options).get '/solr/admin/collections', params: { action: 'DELETE', name: collection } + def perform(collection, connection_options, tenant_type = 'normal') + if tenant_type == 'cross_search_tenant' + solr_client(connection_options).get '/solr/admin/collections', params: { action: 'DELETEALIAS', name: collection } + else + solr_client(connection_options).get '/solr/admin/collections', params: { action: 'DELETE', name: collection } + end end private diff --git a/app/models/account.rb b/app/models/account.rb index daf533a6f..e967b7768 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -9,10 +9,26 @@ class Account < ApplicationRecord has_many :sites, dependent: :destroy has_many :domain_names, dependent: :destroy + has_many :full_account_cross_searches, + class_name: 'AccountCrossSearch', + dependent: :destroy, + foreign_key: 'search_account_id', + inverse_of: :search_account + has_many :full_accounts, class_name: 'Account', through: :full_account_cross_searches + has_many :search_account_cross_searches, + class_name: 'AccountCrossSearch', + dependent: :destroy, + foreign_key: 'full_account_id', + inverse_of: :full_account + has_many :search_accounts, class_name: 'Account', through: :search_account_cross_searches + accepts_nested_attributes_for :domain_names, allow_destroy: true + accepts_nested_attributes_for :full_accounts + accepts_nested_attributes_for :full_account_cross_searches, allow_destroy: true scope :is_public, -> { where(is_public: true) } scope :sorted_by_name, -> { order("name ASC") } + scope :full_accounts, -> { where(search_only: false) } before_validation do self.tenant ||= SecureRandom.uuid @@ -26,14 +42,14 @@ class Account < ApplicationRecord unless: proc { |a| a.tenant == 'public' } def self.admin_host - host = Settings.multitenancy.admin_host + host = ENV.fetch('HYKU_ADMIN_HOST', nil) host ||= ENV['HOST'] host ||= 'localhost' canonical_cname(host) end def self.root_host - host = Settings.multitenancy.root_host + host = ENV.fetch('HYKU_ROOT_HOST', nil) host ||= ENV['HOST'] host ||= 'localhost' canonical_cname(host) @@ -59,7 +75,7 @@ def self.single_tenant_default def self.global_tenant? # Global tenant only exists when multitenancy is enabled and NOT in test environment # (In test environment tenant switching is currently not possible) - return false unless Settings.multitenancy.enabled && !Rails.env.test? + return false unless ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_MULTITENANT', false)) && !Rails.env.test? Apartment::Tenant.default_tenant == Apartment::Tenant.current end @@ -69,9 +85,8 @@ def switch! fcrepo_endpoint.switch! redis_endpoint.switch! data_cite_endpoint.switch! - # TOOD Settings.switch!(name: locale_name, settings: settings) switch_host!(cname) - setup_tenant_cache(cache_api?) + setup_tenant_cache(cache_api?) if self.class.column_names.include?('settings') end def switch @@ -82,12 +97,11 @@ def switch end def reset! - setup_tenant_cache(cache_api?) + setup_tenant_cache(cache_api?) if self.class.column_names.include?('settings') SolrEndpoint.reset! FcrepoEndpoint.reset! RedisEndpoint.reset! DataCiteEndpoint.reset! - # TODO: Settings.switch! switch_host!(nil) end @@ -103,7 +117,7 @@ def setup_tenant_cache(is_enabled) if is_enabled Rails.application.config.cache_store = :redis_cache_store, { url: Redis.current.id } else - Rails.application.config.cache_store = :file_store, Settings.cache_filesystem_root + Rails.application.config.cache_store = :file_store, ENV.fetch('HYKU_CACHE_ROOT', '/app/samvera/file_cache') end # rubocop:enable Style/ConditionalAssignment Rails.cache = ActiveSupport::Cache.lookup_store(Rails.application.config.cache_store) diff --git a/app/models/account_cross_search.rb b/app/models/account_cross_search.rb new file mode 100644 index 000000000..ad0ff6c44 --- /dev/null +++ b/app/models/account_cross_search.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AccountCrossSearch < ApplicationRecord + belongs_to :search_account, class_name: "Account", inverse_of: :full_account_cross_searches + belongs_to :full_account, class_name: "Account", inverse_of: :search_account_cross_searches + + accepts_nested_attributes_for :search_account + accepts_nested_attributes_for :full_account +end diff --git a/app/models/concerns/account_cname.rb b/app/models/concerns/account_cname.rb index f43d6faf8..0306a1110 100644 --- a/app/models/concerns/account_cname.rb +++ b/app/models/concerns/account_cname.rb @@ -10,12 +10,11 @@ module AccountCname # @param [String] piece the tenant piece of the canonical name # @return [String] full canonical name # @raise [ArgumentError] if piece contains a trailing dot - # @see Settings.multitenancy.default_host def default_cname(piece) return unless piece raise ArgumentError, "param '#{piece}' must not contain trailing dots" if piece =~ /\.\Z/ # rubocop:disable Style/FormatStringToken - default_host = Settings.multitenancy.default_host || "%{tenant}.#{admin_host}" + default_host = ENV.fetch('HYKU_DEFAULT_HOST', "%{tenant}.#{admin_host}") # rubocop:enable Style/FormatStringToken canonical_cname(format(default_host, tenant: piece.parameterize)) end diff --git a/app/models/concerns/account_settings.rb b/app/models/concerns/account_settings.rb index 6334ea122..6dc36cea5 100644 --- a/app/models/concerns/account_settings.rb +++ b/app/models/concerns/account_settings.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +# All settings have a presedence order as follows +# Per Tenant Setting > ENV['HYKU_SETTING_NAME'] > ENV['HYRAX_SETTING_NAME'] > default + module AccountSettings extend ActiveSupport::Concern # rubocop:disable Metrics/BlockLength @@ -12,26 +15,33 @@ module AccountSettings end setting :allow_signup, type: 'boolean', default: true - setting :bulkrax_validations, type: 'boolean' + setting :bulkrax_validations, type: 'boolean', disabled: true setting :cache_api, type: 'boolean', default: false - setting :contact_email, type: 'string' + setting :contact_email, type: 'string', default: 'change-me-in-settings@example.com' + setting :contact_email_to, type: 'string', default: 'change-me-in-settings@example.com' setting :doi_reader, type: 'boolean', default: false setting :doi_writer, type: 'boolean', default: false + setting :file_acl, type: 'boolean', default: true, private: true setting :email_format, type: 'array' - setting :enable_oai_metadata, type: 'string' - setting :file_size_limit, type: 'string' + setting :email_subject_prefix, type: 'string' + setting :enable_oai_metadata, type: 'string', disabled: true + setting :file_size_limit, type: 'string', default: 5.gigabytes.to_s setting :google_analytics_id, type: 'string' - setting :google_scholarly_work_types, type: 'string' + setting :google_scholarly_work_types, type: 'array', disabled: true + setting :geonames_username, type: 'string', default: '' setting :gtm_id, type: 'string' - setting :locale_name, type: 'string' - setting :monthly_email_list, type: 'array' - setting :oai_admin_email, type: 'string' - setting :oai_prefix, type: 'string' - setting :oai_sample_identifier, type: 'string' - setting :shared_login, type: 'boolean' - setting :smtp_settings, type: 'hash', private: true - setting :weekly_email_list, type: 'array' - setting :yearly_email_list, type: 'array' + setting :locale_name, type: 'string', disabled: true + setting :monthly_email_list, type: 'array', disabled: true + setting :oai_admin_email, type: 'string', default: 'changeme@example.com' + setting :oai_prefix, type: 'string', default: 'oai:hyku' + setting :oai_sample_identifier, type: 'string', default: '806bbc5e-8ebe-468c-a188-b7c14fbe34df' + setting :s3_bucket, type: 'string', private: true + setting :shared_login, type: 'boolean', disabled: true + setting :smtp_settings, type: 'hash', private: true, default: {} + setting :solr_collection_options, type: 'hash', default: solr_collection_options + setting :ssl_configured, type: 'boolean', default: false, private: true + setting :weekly_email_list, type: 'array', disabled: true + setting :yearly_email_list, type: 'array', disabled: true store :settings, coder: JSON, accessors: all_settings.keys @@ -48,6 +58,7 @@ module AccountSettings end # rubocop:enable Metrics/BlockLength + # rubocop:disable Metrics/BlockLength class_methods do def setting(name, args) known_type = ['array', 'boolean', 'hash', 'string'].include?(args[:type]) @@ -56,15 +67,62 @@ def setting(name, args) send("#{args[:type]}_settings") << name all_settings[name] = args private_settings << name if args[:private] + + define_method(name) do + value = super() + value ||= ENV.fetch("HYKU_#{name.upcase}", nil) + value ||= ENV.fetch("HYRAX_#{name.upcase}", nil) + value ||= args[:default] + set_type(value, (args[:type]).to_s) + end + end + + def solr_collection_options + { + async: nil, + auto_add_replicas: nil, + collection: { + config_name: ENV.fetch('SOLR_CONFIGSET_NAME', 'hyku') + }, + create_node_set: nil, + max_shards_per_node: nil, + num_shards: 1, + replication_factor: nil, + router: { + name: nil, + field: nil + }, + rule: nil, + shards: nil, + snitch: nil + } end end + # rubocop:enable Metrics/BlockLength def public_settings - settings.reject { |k, _v| Account.private_settings.include?(k.to_s) } + all_settings.reject { |k, v| Account.private_settings.include?(k.to_s) || v[:disabled] } + end + + def live_settings + all_settings.reject { |_k, v| v[:disabled] } end private + def set_type(value, to_type) + case to_type + when 'array' + value.is_a?(String) ? value.split(',') : Array.wrap(value) + when 'boolean' + value.is_a?(String) ? ['1', 'true'].include?(value) : value + when 'hash' + value.is_a?(String) ? JSON.parse(value) : value + when 'string' + value.to_s + end + end + def validate_email_format return if settings['email_format'].blank? settings['email_format'].each do |email| @@ -82,13 +140,50 @@ def validate_contact_emails end def initialize_settings + return true unless self.class.column_names.include?('settings') set_smtp_settings + reload_library_config end def set_smtp_settings - current_smtp_settings = settings["smtp_settings"].presence || {} + current_smtp_settings = settings&.[]("smtp_settings").presence || {} self.smtp_settings = current_smtp_settings.with_indifferent_access.reverse_merge!( PerTenantSmtpInterceptor.available_smtp_fields.each_with_object("").to_h ) end + + def reload_library_config + Hyrax.config do |config| + config.contact_email = contact_email + config.analytics = google_analytics_id.present? + config.google_analytics_id = google_analytics_id + config.geonames_username = geonames_username + config.uploader[:maxFileSize] = file_size_limit + end + + Devise.mailer_sender = contact_email + + if s3_bucket.present? + CarrierWave.configure do |config| + config.storage = :aws + config.aws_bucket = s3_bucket + config.aws_acl = 'bucket-owner-full-control' + end + elsif !file_acl + CarrierWave.configure do |config| + config.permissions = nil + config.directory_permissions = nil + end + else + CarrierWave.configure do |config| + config.storage = :file + config.permissions = 420 + config.directory_permissions = 493 + end + end + + return unless ssl_configured + ActionMailer::Base.default_url_options ||= {} + ActionMailer::Base.default_url_options[:protocol] = 'https' + end end diff --git a/app/models/hyrax/contact_form.rb b/app/models/hyrax/contact_form.rb index 33cdc899c..8da30d78e 100644 --- a/app/models/hyrax/contact_form.rb +++ b/app/models/hyrax/contact_form.rb @@ -20,15 +20,15 @@ def spam? # in ActionMailer accepts. ###### OVERRODE the to: field to add the Tenant's email, first def contact_email - Site.contact_email.presence || Settings.contact_email_to + Site.account.contact_email_to end def headers ## override hyrax 2.5.1 send the mail 'from' the submitter, which doesn't work on most smtp transports { - subject: "#{Hyrax.config.subject_prefix} #{email} #{subject}", + subject: "#{Site.account.email_subject_prefix} #{email} #{subject}", to: contact_email, - from: Settings.contact_email, + from: Site.account.contact_email, reply_to: email } end diff --git a/app/models/nil_endpoint.rb b/app/models/nil_endpoint.rb index 78128b9e5..6e60625ed 100644 --- a/app/models/nil_endpoint.rb +++ b/app/models/nil_endpoint.rb @@ -13,4 +13,8 @@ def persisted? def remove! false end + + def assign_attributes(_attr) + false + end end diff --git a/app/models/nil_site.rb b/app/models/nil_site.rb index 17d717e0f..0deabea65 100644 --- a/app/models/nil_site.rb +++ b/app/models/nil_site.rb @@ -15,7 +15,7 @@ def instance attr_reader :id, :account, :application_name, :institution_name, :institution_name_full, :banner_image, :primary_key, :logo_image, :default_collection_image, :default_work_image, - :directory_image, :contact_email + :directory_image # rubocop:disable Lint/DuplicateMethods def reload diff --git a/app/models/redis_endpoint.rb b/app/models/redis_endpoint.rb index 25037adcd..b6899cf98 100644 --- a/app/models/redis_endpoint.rb +++ b/app/models/redis_endpoint.rb @@ -9,7 +9,7 @@ def switch! # Reset the Redis namespace back to the default value def self.reset! - Hyrax.config.redis_namespace = Settings.redis.default_namespace + Hyrax.config.redis_namespace = ENV.fetch('HYRAX_REDIS_NAMESPACE', 'hyrax') end def ping diff --git a/app/models/solr_endpoint.rb b/app/models/solr_endpoint.rb index 032e0d21f..728f388f3 100644 --- a/app/models/solr_endpoint.rb +++ b/app/models/solr_endpoint.rb @@ -30,7 +30,11 @@ def switch! # Remove the solr collection then destroy this record def remove! # Spin off as a job, so that it can fail and be retried separately from the other logic. - RemoveSolrCollectionJob.perform_later(collection, connection_options) + if account.search_only? + RemoveSolrCollectionJob.perform_later(collection, connection_options, 'cross_search_tenant') + else + RemoveSolrCollectionJob.perform_later(collection, connection_options) + end destroy end diff --git a/app/services/create_account.rb b/app/services/create_account.rb index 1b4329ac1..042cf75ec 100644 --- a/app/services/create_account.rb +++ b/app/services/create_account.rb @@ -40,6 +40,8 @@ def create_tenant end def create_defaults + return if account.search_only? + Hyrax::CollectionType.find_or_create_default_collection_type Hyrax::CollectionType.find_or_create_admin_set_type AdminSet.find_or_create_default_admin_set_id diff --git a/app/views/_head_tag_extras.html.erb b/app/views/_head_tag_extras.html.erb new file mode 100644 index 000000000..6a73da42e --- /dev/null +++ b/app/views/_head_tag_extras.html.erb @@ -0,0 +1 @@ +<%= render_gtm_head(request.original_url) %> diff --git a/app/views/admin/accounts/edit.html.erb b/app/views/admin/accounts/edit.html.erb index 52684348f..e03fcb9fd 100644 --- a/app/views/admin/accounts/edit.html.erb +++ b/app/views/admin/accounts/edit.html.erb @@ -5,7 +5,7 @@
diff --git a/app/views/contacts/edit.html.erb b/app/views/contacts/edit.html.erb deleted file mode 100644 index 6d2657e55..000000000 --- a/app/views/contacts/edit.html.erb +++ /dev/null @@ -1,35 +0,0 @@ -<% content_for :page_header do %> -

<%= t(:'hyrax.admin.sidebar.contact') %>

-<% end %> - -
-
-
- <%= form_for(@site, url: site_contact_path) do |f| %> -
-

Contact

-
-
- <% if @site.errors.any? %> -
-

<%= pluralize(@site.errors.count, "error") %> prohibited this site from being saved:

- -
    - <% @site.errors.full_messages.each do |message| %> -
  • <%= message %>
  • - <% end %> -
-
- <% end %> -
- <%= f.label :contact_email %>
- <%= f.text_field :contact_email, class: 'form-control'%> -
-
- - <% end %> -
-
-
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb index a4bebe21c..7fc4259ca 100644 --- a/app/views/devise/shared/_links.html.erb +++ b/app/views/devise/shared/_links.html.erb @@ -2,7 +2,7 @@ <%= link_to t(".sign_in"), new_session_path(resource_name) %>
<% end -%> -<%- if devise_mapping.registerable? && controller_name != 'registrations' %> +<%- if devise_mapping.registerable? && controller_name != 'registrations' && !Account.global_tenant? && current_account.try(:allow_signup) == "true" %> <%= link_to t(".sign_up"), new_registration_path(resource_name) %>
<% end -%> diff --git a/app/views/gtm/_gtm_body.html.erb b/app/views/gtm/_gtm_body.html.erb new file mode 100644 index 000000000..024f5fd52 --- /dev/null +++ b/app/views/gtm/_gtm_body.html.erb @@ -0,0 +1,12 @@ +<% content_for :precontainer_content do %> + <% tenant_gtm_id = current_account.settings['gtm_id'] %> + <% return '' if tenant_gtm_id.blank? %> + + <<-HTML.strip_heredoc.html_safe + + + + + +<% end %> diff --git a/app/views/gtm/_gtm_head.html.erb b/app/views/gtm/_gtm_head.html.erb new file mode 100644 index 000000000..800435b0d --- /dev/null +++ b/app/views/gtm/_gtm_head.html.erb @@ -0,0 +1,15 @@ +<% content_for :head do %> + <% tenant_gtm_id = current_account.settings['gtm_id'] %> + <% return '' if tenant_gtm_id.blank? %> + + <<-HTML.strip_heredoc.html_safe + + + +<% end %> diff --git a/app/views/hyrax/dashboard/sidebar/_configuration.html.erb b/app/views/hyrax/dashboard/sidebar/_configuration.html.erb index 6df412f31..4d37c0b7e 100644 --- a/app/views/hyrax/dashboard/sidebar/_configuration.html.erb +++ b/app/views/hyrax/dashboard/sidebar/_configuration.html.erb @@ -1,47 +1,49 @@ - <% if menu.show_configuration? %> -
  • <%= t('hyrax.admin.sidebar.configuration') %>
  • - <% if can? :manage, Site %> -
  • - <%= menu.collapsable_section t('hyrax.admin.sidebar.settings'), - icon_class: "fa fa-cog", - id: 'collapseSettings', - open: menu.settings_section? do %> - <%= menu.nav_link(main_app.edit_site_contact_path) do %> - <%= t('hyrax.admin.sidebar.contact') %> - <% end %> - <%= menu.nav_link(main_app.edit_site_labels_path) do %> - <%= t('hyrax.admin.sidebar.labels') %> - <% end %> - <% if can?(:update, :appearance) %> - <%= menu.nav_link(hyrax.admin_appearance_path) do %> - <%= t('hyrax.admin.sidebar.appearance') %> - <% end %> - <% end %> - <% if can?(:manage, :collection_types) %> - <%= menu.nav_link(hyrax.admin_collection_types_path) do %> - <%= t('hyrax.admin.sidebar.collection_types') %> +<% if menu.show_configuration? %> +
  • <%= t('hyrax.admin.sidebar.configuration') %>
  • + <% if can? :manage, Site %> +
  • + <%= menu.collapsable_section t('hyrax.admin.sidebar.settings'), + icon_class: "fa fa-cog", + id: 'collapseSettings', + open: menu.settings_section? do %> + + <%= menu.nav_link(main_app.edit_admin_account_path) do %> + <%= t('hyrax.admin.sidebar.account') %> <% end %> - <% end %> - <% if can?(:manage, Hyrax::Feature) %> - <%= menu.nav_link(hyrax.edit_pages_path) do %> - <%= t('hyrax.admin.sidebar.pages') %> + + <%= menu.nav_link(main_app.edit_site_labels_path) do %> + <%= t('hyrax.admin.sidebar.labels') %> <% end %> - <%= menu.nav_link(hyrax.edit_content_blocks_path) do %> - <%= t('hyrax.admin.sidebar.content_blocks') %> + <% if can?(:update, :appearance) %> + <%= menu.nav_link(hyrax.admin_appearance_path) do %> + <%= t('hyrax.admin.sidebar.appearance') %> + <% end %> <% end %> - <%= menu.nav_link(hyrax.admin_features_path) do %> - <%= t('hyrax.admin.sidebar.technical') %> + <% if can?(:manage, :collection_types) %> + <%= menu.nav_link(hyrax.admin_collection_types_path) do %> + <%= t('hyrax.admin.sidebar.collection_types') %> + <% end %> <% end %> - <%= menu.nav_link('/admin/work_types/edit') do %> - <%= t('hyku.admin.work_types') %> + <% if can?(:manage, Hyrax::Feature) %> + <%= menu.nav_link(hyrax.edit_pages_path) do %> + <%= t('hyrax.admin.sidebar.pages') %> + <% end %> + <%= menu.nav_link(hyrax.edit_content_blocks_path) do %> + <%= t('hyrax.admin.sidebar.content_blocks') %> + <% end %> + <%= menu.nav_link(hyrax.admin_features_path) do %> + <%= t('hyrax.admin.sidebar.technical') %> + <% end %> + <%= menu.nav_link('/admin/work_types/edit') do %> + <%= t('hyku.admin.work_types') %> + <% end %> <% end %> +
  • <% end %> - - <% end %> - <% if can?(:manage, Sipity::WorkflowResponsibility) %> - <%= menu.nav_link(hyrax.admin_workflow_roles_path) do %> - <%= t('hyrax.admin.sidebar.workflow_roles') %> - <% end %> - <% end # end of configuration block %> + <% if can?(:manage, Sipity::WorkflowResponsibility) %> + <%= menu.nav_link(hyrax.admin_workflow_roles_path) do %> + <%= t('hyrax.admin.sidebar.workflow_roles') %> + <% end %> + <% end # end of configuration block %> <% end %> <% end %> diff --git a/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb b/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb index 16fdfe966..89e03651c 100644 --- a/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb +++ b/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb @@ -11,7 +11,7 @@ <%= t('hyrax.admin.sidebar.works') %> <% end %> -<% if Settings.bulkrax.enabled %> +<% if ENV.fetch('HYKU_BULKRAX_ENABLED', false) %> <%= menu.nav_link(bulkrax.importers_path) do %> <%= t('bulkrax.admin.sidebar.importers') %> <% end %> diff --git a/app/views/layouts/hyrax.html.erb b/app/views/layouts/hyrax.html.erb index 9926856cf..266efb7f9 100644 --- a/app/views/layouts/hyrax.html.erb +++ b/app/views/layouts/hyrax.html.erb @@ -8,6 +8,7 @@ <% content_for(:extra_body_classes, 'public-facing') unless params[:controller].match(/^proprietor/) %> + <%= render_gtm_body(request.original_url) %>
    <%= link_to "Skip to Content", "#skip-to-content" %>
    diff --git a/app/views/proprietor/accounts/_domain_name_fields.html.erb b/app/views/proprietor/accounts/_domain_name_fields.html.erb new file mode 100644 index 000000000..a5820adb7 --- /dev/null +++ b/app/views/proprietor/accounts/_domain_name_fields.html.erb @@ -0,0 +1,6 @@ +
    + <%= f.input :cname %> + <%= f.input :is_active %> + <%= link_to_remove_association "remove domain name", f %> + +
    diff --git a/app/views/proprietor/accounts/_full_account_cross_search_fields.html.erb b/app/views/proprietor/accounts/_full_account_cross_search_fields.html.erb new file mode 100644 index 000000000..1e7320880 --- /dev/null +++ b/app/views/proprietor/accounts/_full_account_cross_search_fields.html.erb @@ -0,0 +1,4 @@ +
    + <%= f.association :full_account, collection: Account.full_accounts %> + <%= link_to_remove_association "remove", f %> +
    diff --git a/app/views/proprietor/accounts/edit.html.erb b/app/views/proprietor/accounts/edit.html.erb index 5a4f974f6..ecd8f376c 100644 --- a/app/views/proprietor/accounts/edit.html.erb +++ b/app/views/proprietor/accounts/edit.html.erb @@ -18,45 +18,60 @@
    <% end %> - <%= f.input :is_public, hint: 'Can users discover your site on the home page or access your pages without a special username / password?' %> + <%= f.input :is_public %> <%= f.input :tenant, readonly: @account.persisted? %> - <%= f.input :cname %> -

    <%= t(".solr_endpoint") %>

    - <%= f.simple_fields_for :solr_endpoint do |s| %> - <%= s.input :url %> + <%= f.input :cname, readonly: true %> +
    +

    Domain Names

    + <%= f.simple_fields_for :domain_names do |domain_name| %> + <%= render 'domain_name_fields', f: domain_name %> + <% end %> +
    + <%= link_to_add_association 'add domain name', f, :domain_names %> +
    +
    + +

    <%= t(".account_settings") %>

    + <% current_account.live_settings.each do |key, value| %> + <%= render 'shared/settings', f: f, key: key, value: value %> <% end %> -

    <%= t(".fcrepo_endpoint") %>

    - <%= f.fields_for :fcrepo_endpoint do |s| %> - <%= s.input :url %> - <%= s.input :base_path %> + <% if @account.search_only? %> +

    <%= t('.accounts_to_search') %>

    +
    + <%= f.simple_fields_for :full_account_cross_searches do |full_account_cross_search| %> + <%= render 'full_account_cross_search_fields', f: full_account_cross_search %> + <% end %> +
    + <%= link_to_add_association 'Add account to search', f, :full_account_cross_searches %> +
    +
    <% end %> - <% if current_account.doi_writer || current_account.doi_reader %> + <% unless @account.search_only? %>

    <%= t(".datacite_endpoint") %>

    <%= f.fields_for :datacite_endpoint do |s| %> <%= s.input :mode, required: false %> <%= s.input :prefix, required: false %> <%= s.input :username, required: false %> - <%= s.input :password, input_html: { value: @account.datacite_endpoint.password }, required: false %> + <%= s.input :password, input_html: { value: @account.data_cite_endpoint.password }, required: false %> <% end %> - <% end %> - -

    <%= t(".account_settings") %>

    + <% end %> - <%= f.fields_for :settings do |s| %> - <%= s.label "file_size_limit", required: false %>
    - <%= s.text_field 'file_size_limit', value: @account.settings['file_size_limit'], class: 'form-control' %> -

    <%= t("settings.helptexts.file_size_limit") %>

    - <% end %> +

    <%= t(".solr_endpoint") %>

    + <%= f.simple_fields_for :solr_endpoint do |s| %> + <%= s.input :url, required: false %> + <% end %> - <%= f.fields_for :settings do |s| %> - <%= s.label "locale_name", required: false %>
    - <%= s.text_field 'locale_name', value: @account.settings['locale_name'], class: "form-control" %> -

    <%= t("settings.helptexts.locale_name") %>

    - <% end %> + <% unless @account.search_only? %> +

    <%= t(".fcrepo_endpoint") %>

    + <%= f.fields_for :fcrepo_endpoint do |s| %> + <%= s.input :url %> + <%= s.input :base_path %> + <% end %> + <% end %> <%= f.submit class: 'btn btn-primary' %> <%= link_to t('simple_form.cancel'), proprietor_accounts_path, class: 'btn btn-link action-cancel' %> diff --git a/app/views/proprietor/accounts/new.html.erb b/app/views/proprietor/accounts/new.html.erb index 1cd8003b4..b46843908 100644 --- a/app/views/proprietor/accounts/new.html.erb +++ b/app/views/proprietor/accounts/new.html.erb @@ -19,6 +19,18 @@ <% end %> <%= f.input :name %> + <%= f.input :search_only %> + +
    +
    + <%= f.simple_fields_for :full_account_cross_searches do |full_account_cross_search| %> + <%= render 'full_account_cross_search_fields', f: full_account_cross_search %> + <% end %> +
    + <%= link_to_add_association 'Add account to search', f, :full_account_cross_searches %> +
    +
    +
    <%= f.submit class: 'btn btn-primary' %> <%= link_to t('simple_form.cancel'), proprietor_accounts_path, class: 'btn btn-link action-cancel' %> diff --git a/app/views/shared/_settings.html.erb b/app/views/shared/_settings.html.erb new file mode 100644 index 000000000..ebeeeaad6 --- /dev/null +++ b/app/views/shared/_settings.html.erb @@ -0,0 +1,8 @@ +<% if value[:type] == 'array' %> + <% current_account.send(key).each do |sub_value| %> + <%= f.input key, value: sub_value %> + <% end %> +<% elsif value[:type] == 'hash' %> +<% else %> + <%= f.input key, as: value[:type] %> +<% end %> diff --git a/app/views/splash/index.html.erb b/app/views/splash/index.html.erb index 6ac0cd16b..89b379ab0 100644 --- a/app/views/splash/index.html.erb +++ b/app/views/splash/index.html.erb @@ -5,7 +5,7 @@

    <%= application_name %>

    <%= t('application.tagline') %>

    - <% if !Settings.multitenancy.admin_only_tenant_creation || can?(:manage, Account) %> + <% if !admin_only_tenant_creation? || can?(:manage, Account) %> <%= link_to t('hyku.splash.account_signup'), account_sign_up_path, class: 'btn btn-lg btn-sign-up' %> <% elsif !user_signed_in? %> <%= link_to t('hyku.splash.account_login'), main_app.new_user_session_path, class: 'btn btn-lg btn-sign-up' %> diff --git a/config/application.rb b/config/application.rb index 6bc893928..55d545611 100644 --- a/config/application.rb +++ b/config/application.rb @@ -6,7 +6,7 @@ # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. groups = Rails.groups -groups += ['bulkrax'] if ENV['SETTINGS__BULKRAX__ENABLED'] == 'true' # Settings obj is not available yet +groups += ['bulkrax'] if ENV['HYKU_BULKRAX_ENABLED'] == 'true' # Settings obj is not available yet Bundler.require(*groups) module Hyku @@ -24,9 +24,10 @@ class Application < Rails::Application "I18n::InvalidLocale" => :not_found ) - if defined? ActiveElasticJob + if defined?(ActiveElasticJob) && ENV.fetch('HYRAX_ACTIVE_JOB_QUEUE', '') == 'elastic' Rails.application.configure do - config.active_elastic_job.process_jobs = Settings.worker == 'true' + process_jobs = ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_ELASTIC_JOBS', false)) + config.active_elastic_job.process_jobs = process_jobs config.active_elastic_job.aws_credentials = lambda { Aws::InstanceProfileCredentials.new } config.active_elastic_job.secret_key_base = Rails.application.secrets[:secret_key_base] end @@ -36,9 +37,10 @@ class Application < Rails::Application config.paths.add 'app/helpers', eager_load: true config.before_initialize do - if defined? ActiveElasticJob + if defined?(ActiveElasticJob) && ENV.fetch('HYRAX_ACTIVE_JOB_QUEUE', '') == 'elastic' Rails.application.configure do - config.active_elastic_job.process_jobs = Settings.worker == 'true' + process_jobs = ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_ELASTIC_JOBS', false)) + config.active_elastic_job.process_jobs = process_jobs config.active_elastic_job.aws_credentials = lambda { Aws::InstanceProfileCredentials.new } config.active_elastic_job.secret_key_base = Rails.application.secrets[:secret_key_base] end @@ -46,7 +48,7 @@ class Application < Rails::Application Object.include(AccountSwitch) - if Settings.bulkrax.enabled + if ENV.fetch('HYKU_BULKRAX_ENABLED', false) Bundler.require('bulkrax') end end diff --git a/config/environments/development.rb b/config/environments/development.rb index 9744099a2..c62ee17d0 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -58,7 +58,8 @@ config.logger = ActiveSupport::TaggedLogging.new(logger) end - config.active_job.queue_adapter = Settings.active_job.queue_adapter + config.active_job.queue_adapter = ENV.fetch('HYRAX_ACTIVE_JOB_QUEUE', 'sidekiq') + # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. # config.file_watcher = ActiveSupport::EventedFileUpdateChecker diff --git a/config/environments/production.rb b/config/environments/production.rb index b468e4ded..4d96ece5f 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -31,7 +31,7 @@ # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb # Enable serving of images, stylesheets, and JavaScripts from an asset server. - config.action_controller.asset_host = Settings.action_controller.asset_host if Settings.action_controller.asset_host + config.action_controller.asset_host = ENV.fetch("HYKU_ASSET_HOST", nil) # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache @@ -57,7 +57,7 @@ # Use a real queuing backend for Active Job (and separate queues per environment) require 'active_job/queue_adapters/better_active_elastic_job_adapter' - config.active_job.queue_adapter = Settings.active_job.queue_adapter + config.active_job.queue_adapter = ENV.fetch('HYRAX_ACTIVE_JOB_QUEUE', 'sidekiq') # config.active_job.queue_name_prefix = "hyku_#{Rails.env}" if ENV['SMTP_ENABLED'].present? && ENV['SMTP_ENABLED'].to_s == 'true' @@ -74,7 +74,7 @@ config.action_mailer.delivery_method = :smtp config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = false - config.action_mailer.asset_host = ENV['SETTINGS__MULTITENANCY__ADMIN_HOST'] + config.action_mailer.asset_host = ENV['HYKU_ADMIN_HOST'] else config.action_mailer.delivery_method = :test end @@ -85,7 +85,9 @@ # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false # - config.action_mailer.default_url_options = { protocol: Settings.ssl_configured ? 'https' : 'http' } + + # Mailer ssl and url configured in accountsettings + # config.action_mailer.default_url_options = { protocol: 'https' } # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index d89b5a93b..e937e69d9 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -12,7 +12,7 @@ # Add any models that you do not want to be multi-tenanted, but remain in the global (public) namespace. # A typical example would be a Customer or Tenant model that stores each Tenant's information. - config.excluded_models = %w{ Account DomainName Endpoint User UserStat SolrEndpoint FcrepoEndpoint RedisEndpoint } + config.excluded_models = %w{ Account AccountCrossSearch DomainName Endpoint User UserStat SolrEndpoint FcrepoEndpoint RedisEndpoint } # In order to migrate all of your Tenants you need to provide a list of Tenant names to Apartment. # You can make this dynamic by providing a Proc object to be called on migrations. diff --git a/config/initializers/bulkrax.rb b/config/initializers/bulkrax.rb index 2375d09a2..92f32dee7 100644 --- a/config/initializers/bulkrax.rb +++ b/config/initializers/bulkrax.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -if Settings.bulkrax.enabled +if ENV.fetch('HYKU_BULKRAX_ENABLED', false) Bulkrax.setup do |config| # Add local parsers diff --git a/config/initializers/carrierwave_config.rb b/config/initializers/carrierwave_config.rb deleted file mode 100644 index c9ac0d096..000000000 --- a/config/initializers/carrierwave_config.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'carrierwave' - -if Settings.s3.upload_bucket - CarrierWave.configure do |config| - # config.fog_provider = 'fog/aws' # we use carrierwave-aws instead of fog now - # config.fog_credentials = { - # provider: 'AWS', - # use_iam_profile: true - # } - config.storage = :aws - config.aws_bucket = Settings.s3.upload_bucket - config.aws_acl = 'bucket-owner-full-control' - end -elsif !Settings.file_acl || Settings.file_acl == 'false' - CarrierWave.configure do |config| - config.permissions = nil - config.directory_permissions = nil - end -end diff --git a/config/initializers/config.rb b/config/initializers/config.rb deleted file mode 100644 index 7602c41bc..000000000 --- a/config/initializers/config.rb +++ /dev/null @@ -1,13 +0,0 @@ -Config.setup do |config| - # Name of the constat exposing loaded settings - config.const_name = 'Settings' - - config.use_env = true - config.env_prefix = 'SETTINGS' - config.env_separator = '__' - config.env_converter = :downcase - config.env_parse_values = true - - # Ability to remove elements of the array set in earlier loaded settings file. Default: nil - # config.knockout_prefix = '--' -end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 05a789ab4..61368db07 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -12,7 +12,7 @@ # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class # with default "from" parameter. - config.mailer_sender = Settings.devise.invitation_from_email + config.mailer_sender = ENV.fetch('HYKU_CONTACT_EMAIL', 'changeme@example.com') # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' diff --git a/config/initializers/hyrax.rb b/config/initializers/hyrax.rb index 52fe677f5..a00470115 100644 --- a/config/initializers/hyrax.rb +++ b/config/initializers/hyrax.rb @@ -4,7 +4,8 @@ config.register_curation_concern :image # Email recipient of messages sent via the contact form - config.contact_email = Settings.contact_email + # This is set by account settings + # config.contact_email = 'changeme@example.com' # Text prefacing the subject entered in the contact form # config.subject_prefix = "Contact form:" @@ -18,10 +19,12 @@ # Enable displaying usage statistics in the UI # Defaults to FALSE # Requires a Google Analytics id and OAuth2 keyfile. See README for more info - config.analytics = Settings.google_analytics_id.present? + # This is set by account settings + # config.analytics = false # Specify a Google Analytics tracking ID to gather usage statistics - config.google_analytics_id = Settings.google_analytics_id + # This is set by account settings + # config.google_analytics_id = 'UA-99999999-1' # Specify a date you wish to start collecting Google Analytic statistics for. # config.analytic_start_date = DateTime.new(2014,9,10) @@ -50,13 +53,14 @@ # config.minter_statefile = '/tmp/minter-state' # Specify the prefix for Redis keys: - config.redis_namespace = Settings.redis.default_namespace + # Note this is only the default namespace for the proritor section. Tenants get their own namespace + config.redis_namespace = ENV.fetch('HYRAX_REDIS_NAMESPACE', 'hyrax') # Specify the path to the file characterization tool: - config.fits_path = Settings.fits_path + config.fits_path = ENV.fetch('HYRAX_FITS_PATH', '/app/fits/fits.sh') # Specify the path to the file derivatives creation tool: - # config.libreoffice_path = "soffice" + config.libreoffice_path = ENV.fetch('HYRAX_LIBREOFFICE_PATH', 'soffice') # Stream realtime notifications to users in the browser # config.realtime_notifications = true @@ -80,7 +84,8 @@ # Location autocomplete uses geonames to search for named regions. # Specify the user for connecting to geonames: - config.geonames_username = Settings.geonames_username + # This is set in account settings + # config.geonames_username = '' # Should the acceptance of the licence agreement be active (checkbox), or # implied when the save button is pressed? Set to true for active. @@ -107,7 +112,7 @@ # Temporary path to hold uploads before they are ingested into FCrepo. # This must be a lambda that returns a Pathname config.upload_path = ->() do - if Settings.s3.upload_bucket + if Site.account&.s3_bucket "uploads/#{Apartment::Tenant.current}" else ENV['HYRAX_UPLOAD_PATH'].present? ? Pathname.new(File.join(ENV['HYRAX_UPLOAD_PATH'], Apartment::Tenant.current)) : Rails.root.join('public', 'uploads', Apartment::Tenant.current) @@ -134,11 +139,12 @@ # config.display_media_download_link = true # Options to control the file uploader - # config.uploader = { - # limitConcurrentUploads: 6, - # maxNumberOfFiles: 100, - # maxFileSize: 500.megabytes - # } + # Max size is set in accountsettings + config.uploader = { + limitConcurrentUploads: 6, + maxNumberOfFiles: 100, + maxFileSize: 5.gigabytes + } # Fedora import/export tool # @@ -160,18 +166,18 @@ # config.browse_everything = nil # end config.browse_everything = nil - + config.iiif_image_server = true - + config.iiif_image_url_builder = lambda do |file_id, base_url, size| Riiif::Engine.routes.url_helpers.image_url(file_id, host: base_url, size: size) end - + config.iiif_info_url_builder = lambda do |file_id, base_url| uri = Riiif::Engine.routes.url_helpers.info_url(file_id, host: base_url) uri.sub(%r{/info\.json\Z}, '') end - + end Date::DATE_FORMATS[:standard] = "%m/%d/%Y" @@ -181,6 +187,6 @@ Qa::Authorities::Local.register_subauthority('genres', 'Qa::Authorities::Local::TableBasedAuthority') # set bulkrax default work type to first curation_concern if it isn't already set -if Settings.bulkrax.enabled && Bulkrax.default_work_type.blank? +if ENV.fetch('HYKU_BULKRAX_ENABLED', false) && Bulkrax.default_work_type.blank? Bulkrax.default_work_type = Hyrax.config.curation_concerns.first.to_s end diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb index fcacca965..bda68ab4d 100644 --- a/config/initializers/secure_headers.rb +++ b/config/initializers/secure_headers.rb @@ -1,6 +1,6 @@ SecureHeaders::Configuration.default do |config| config.cookies = { - secure: ActiveRecord::Type::Boolean.new.cast(Settings.ssl_configured) || SecureHeaders::OPT_OUT, + secure: ActiveRecord::Type::Boolean.new.cast(ENV.fetch('HYKU_SSL_CONFIGURED', false)) || SecureHeaders::OPT_OUT, httponly: true, # mark all cookies as "HttpOnly" samesite: { strict: true # mark all cookies as SameSite=Strict diff --git a/config/locales/en.yml b/config/locales/en.yml index e64c01957..cd56f8856 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -124,25 +124,6 @@ en: last_login: Last access name: Name user_key: Username - settings: - helptexts: - gtm_id: The ID of your Google Tag Manager account - contact_email: Email recipient of messages sent via the contact form - weekly_email_list: List of email addresses to email the weekly report. Leave a single space between each email - monthly_email_list: List of email addresses to email the monthly report. Leave a single space between each email - yearly_email_list: List of email addresses to email the yearly report. Leave a single space between each email - email_format: Set a list of email domains that are allowed sign up to this repository e.g (@ubiquitypress.com @gmail.com). Leave a single space between each domain. - allow_signup: Allow users to sign up to your repository - enable_oai_metadata: Enable or disable OAI link - shared_login: Enable or disable shared login - file_size_limit: This should be set to 536870912000 - locale_name: | - The name of the tenant specific locale suffix added to their locale.yml files. Only alphabetic characters should be added, no symbols or numbers, these will then be capitalised. - oai_admin_email: OAI endpoint contact email address - doi_reader: Show ability to read from Datacite to populate records. WIP do not use - doi_writer: Write DOIs for records. WIP do not use - cache_api: Turns on cache for API endpoints. Experimental - hyrax: admin: appearances: diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 1e85bc970..da26f16e7 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -7,10 +7,32 @@ en: hints: account: admin_emails: Enter one email address at a time + is_public: 'Can users discover your site on the home page or access your pages without a special username / password?' fcrepo_endpoint: base_path: Fedora base path should begin with a slash AND not end with a slash url: Fedora URL should not end with a slash name: A single or hyphenated name used for technical aspects of the repository (e.g., "acme" or "acme-library"). + gtm_id: The ID of your Google Tag Manager account + contact_email: Email recipient of messages sent via the contact form + weekly_email_list: List of email addresses to email the weekly report. Leave a single space between each email + monthly_email_list: List of email addresses to email the monthly report. Leave a single space between each email + yearly_email_list: List of email addresses to email the yearly report. Leave a single space between each email + email_format: Set a list of email domains that are allowed sign up to this repository e.g (@ubiquitypress.com @gmail.com). Leave a single space between each domain. + allow_signup: Allow users to sign up to your repository + enable_oai_metadata: Enable or disable OAI link + shared_login: Enable or disable shared login + file_size_limit: This should be set to at least 536870912000 + locale_name: | + The name of the tenant specific locale suffix added to their locale.yml files. Only alphabetic characters should be added, no symbols or numbers, these will then be capitalised. + oai_admin_email: OAI endpoint contact email address + doi_reader: Show ability to read from Datacite to populate records. WIP do not use + doi_writer: Write DOIs for records. WIP do not use + cache_api: Turns on cache for API endpoints. Experimental + email_subjet_prefix: String to put in front of system email subjects. + contact_email_to: Email address that should receive contact emails + geonames_username: Register at http://www.geonames.org/manageaccount + file_acl: Turn off if using a file system like samba or nfs that does not support setting access control lists + ssl_configured: Set it true if using https hyku_group: description: A brief summary of the role of the group user: @@ -18,7 +40,7 @@ en: labels: account: admin_emails: Add or invite new administrator (via email) - cname: Tenant CNAME + cname: Primary Domain Name fcrepo_endpoint: base_path: Base Path url: URL @@ -26,8 +48,11 @@ en: solr_endpoint: url: URL tenant: Tenant UUID + gtm_id: Google tag manager add_user_to_group: user_ids: User ID + domain_names: + cname: Domain Name group_search: q: Search hyku_group: diff --git a/config/routes.rb b/config/routes.rb index 19ec3c097..9b4e83986 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,7 @@ mount Sidekiq::Web => '/sidekiq' end - if Settings.multitenancy.enabled + if ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_MULTITENANT', false)) constraints host: Account.admin_host do get '/account/sign_up' => 'account_sign_up#new', as: 'new_sign_up' post '/account/sign_up' => 'account_sign_up#create' @@ -32,7 +32,6 @@ resource :site, only: [:update] do resources :roles, only: [:index, :update] resource :labels, only: [:edit, :update] - resource :contact, only: [:edit, :update] end root 'hyrax/homepage#index' @@ -42,7 +41,7 @@ mount Blacklight::Engine => '/' mount Hyrax::Engine, at: '/' - if Settings.bulkrax.enabled + if ENV.fetch('HYKU_BULKRAX_ENABLED', false) mount Bulkrax::Engine, at: '/' end diff --git a/config/settings.yml b/config/settings.yml deleted file mode 100644 index d309711ba..000000000 --- a/config/settings.yml +++ /dev/null @@ -1,75 +0,0 @@ -# These settings can also be provided as environment variables, in the form, e.g.: -# SETTINGS__ACTIVE_JOB_QUEUE__URL=http://... -# -# The mapping is described in `./config/initializers/config.rb`. -# -multitenancy: - enabled: false - default_host: # "%{tenant}.dev" - admin_host: - admin_only_tenant_creation: true - root_host: - -ssl_configured: false -file_acl: true - -action_controller: - asset_host: - -redis: - default_namespace: hyku - -solr: - url: "http://127.0.0.1:8983/solr/" - configset: hyku - configset_source_path: <%= File.join(Rails.root, 'solr', 'config') %> - collection_options: - async: - auto_add_replicas: - collection: - config_name: hyku - create_node_set: - max_shards_per_node: - num_shards: 1 - replication_factor: - router: - name: - field: - rule: - shards: - snitch: - -active_job: - queue_adapter: :async - -active_job_queue: - url: - -s3: - upload_bucket: - -fits_path: "fits.sh" - -google_analytics_id: - -# Register here: http://www.geonames.org/manageaccount -geonames_username: 'jcoyne' - -# The address to which the contact form is submitted -contact_email: "change-me-in-hyku-settings@example.org" -contact_email_to: "" - -devise: - account_signup: true - # The address from which user invitations are sent - invitation_from_email: "change-me-in-hyku-settings@example.org" - -oai: - name: Hyku - url: http://example.org/catalog/oai - prefix: oai:hyku - email: change-me-in-hyku-settings@example.org - sample_id: 806bbc5e-8ebe-468c-a188-b7c14fbe34df - -bulkrax: - enabled: false diff --git a/config/solr.yml b/config/solr.yml index cd4368c7c..74612d65a 100644 --- a/config/solr.yml +++ b/config/solr.yml @@ -1,8 +1,7 @@ # This is a sample config file that points to a solr server for each environment -# TODO: there's also a Settings.solr.url configuration that is used in multitenant environments development: url: <%= ENV['SOLR_URL'] || "http://127.0.0.1:#{ENV.fetch('SOLR_DEVELOPMENT_PORT', 8983)}/solr/hydra-development" %> test: url: <%= ENV['SOLR_URL'] ? ENV['SOLR_URL'] + 'hydra-test' : "http://127.0.0.1:#{ENV.fetch('SOLR_TEST_PORT', 8985)}/solr/hydra-test" %> production: - url: <%= ENV['SOLR_URL'] || "http://your.production.server:8080/bl_solr/core0" %> + url: <%= ENV['SOLR_URL'] || "http://#{ENV.fetch('SOLR_ADMIN_USER', 'admin')}:#{ENV.fetch('SOLR_ADMIN_PASSWORD', 'admin')}@#{ENV.fetch('SOLR_HOST', 'solr')}:#{ENV.fetch('SOLR_PORT', '8983')}/solr/" %> diff --git a/db/migrate/20210920061254_create_account_cross_searches.rb b/db/migrate/20210920061254_create_account_cross_searches.rb new file mode 100644 index 000000000..5e7c724d9 --- /dev/null +++ b/db/migrate/20210920061254_create_account_cross_searches.rb @@ -0,0 +1,10 @@ +class CreateAccountCrossSearches < ActiveRecord::Migration[5.2] + def change + create_table :account_cross_searches do |t| + t.references :search_account, foreign_key: { to_table: :accounts } + t.references :full_account, foreign_key: { to_table: :accounts } + + t.timestamps + end + end +end diff --git a/db/migrate/20210920065530_add_search_only_to_account.rb b/db/migrate/20210920065530_add_search_only_to_account.rb new file mode 100644 index 000000000..aa6d86b24 --- /dev/null +++ b/db/migrate/20210920065530_add_search_only_to_account.rb @@ -0,0 +1,5 @@ +class AddSearchOnlyToAccount < ActiveRecord::Migration[5.2] + def change + add_column :accounts, :search_only, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 728e0e7ad..434ca0c98 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,20 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_09_04_215623) do +ActiveRecord::Schema.define(version: 2021_09_20_065530) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "account_cross_searches", force: :cascade do |t| + t.bigint "search_account_id" + t.bigint "full_account_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["full_account_id"], name: "index_account_cross_searches_on_full_account_id" + t.index ["search_account_id"], name: "index_account_cross_searches_on_search_account_id" + end + create_table "accounts", id: :serial, force: :cascade do |t| t.string "tenant" t.string "cname" @@ -27,6 +36,7 @@ t.boolean "is_public", default: false t.jsonb "settings", default: {} t.bigint "data_cite_endpoint_id" + t.boolean "search_only", default: false t.index ["cname", "tenant"], name: "index_accounts_on_cname_and_tenant" t.index ["cname"], name: "index_accounts_on_cname", unique: true t.index ["data_cite_endpoint_id"], name: "index_accounts_on_data_cite_endpoint_id" @@ -678,6 +688,8 @@ t.index ["work_id"], name: "index_work_view_stats_on_work_id" end + add_foreign_key "account_cross_searches", "accounts", column: "full_account_id" + add_foreign_key "account_cross_searches", "accounts", column: "search_account_id" add_foreign_key "accounts", "endpoints", column: "fcrepo_endpoint_id", on_delete: :nullify add_foreign_key "accounts", "endpoints", column: "redis_endpoint_id", on_delete: :nullify add_foreign_key "accounts", "endpoints", column: "solr_endpoint_id", on_delete: :nullify diff --git a/db/seeds.rb b/db/seeds.rb index 509e0b96e..5ccac4c7e 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,7 +5,7 @@ # solr & fedora for the tenant has been created so we keep # Apartment.seed_after_create = false (the default value) -unless Settings.multitenancy.enabled +unless ActiveModel::Type::Boolean.new.cast(ENV.fetch('HYKU_MULTITENANT', false)) puts "\n== Creating single tenant resources" begin single_tenant_default = Account.find_by(cname: 'single.tenant.default') diff --git a/docker-compose.override-nodory.yml b/docker-compose.override-nodory.yml index 3055355e8..933b923cb 100644 --- a/docker-compose.override-nodory.yml +++ b/docker-compose.override-nodory.yml @@ -12,8 +12,8 @@ services: - "5432:5432" web: environment: - - SETTINGS__MULTITENANCY__ADMIN_HOST=lvh.me - - SETTINGS__MULTITENANCY__DEFAULT_HOST=%{tenant}.lvh.me - - SETTINGS__MULTITENANCY__ROOT_HOST=lvh.me + - HYKU_ADMIN_HOST=lvh.me + - HYKU_DEFAULT_HOST=%{tenant}.lvh.me + - HYKU_ROOT_HOST=lvh.me ports: - "3000:3000" diff --git a/docker-compose.yml b/docker-compose.yml index 71c584097..4de752eb5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -113,8 +113,6 @@ services: - VIRTUAL_PORT=3000 - VIRTUAL_HOST=.hyku.test depends_on: - initialize_app: - condition: service_healthy db: condition: service_started solr: @@ -147,6 +145,7 @@ services: command: bundle exec sidekiq depends_on: check_volumes: + condition: service_completed_successfully db: condition: service_started solr: diff --git a/lib/active_job/queue_adapters/better_active_elastic_job_adapter.rb b/lib/active_job/queue_adapters/better_active_elastic_job_adapter.rb index 64b084be3..b634f701a 100644 --- a/lib/active_job/queue_adapters/better_active_elastic_job_adapter.rb +++ b/lib/active_job/queue_adapters/better_active_elastic_job_adapter.rb @@ -9,15 +9,11 @@ class BetterActiveElasticJobAdapter < ActiveElasticJobAdapter class << self private - # Upstream dynamically calculated queue urls for each job; we'd rather - # route jobs into a pre-determined queue url instead. - def queue_url(*_) - if Settings.active_job_queue.url - Settings.active_job_queue.url - else - super - end - end + # Upstream dynamically calculated queue urls for each job; we'd rather + # route jobs into a pre-determined queue url instead. + def queue_url(*_) + ENV['HYKU_ACTIVE_JOB_QUEUE_URL'] || super + end end end end diff --git a/ops/env.conf b/ops/env.conf deleted file mode 100644 index d69b0b179..000000000 --- a/ops/env.conf +++ /dev/null @@ -1,24 +0,0 @@ -env DATABASE_ADAPTER; -env DATABASE_HOST; -env DATABASE_NAME; -env DATABASE_PASSWORD; -env DATABASE_USER; -env DATBASE_TEST_NAME; -env FEDORA_URL; -env GOOGLE_FONTS_KEY; -env LD_LIBRARY_PATH; -env PASSENGER_APP_ENV; -env RAILS_ENV; -env RAILS_CACHE_STORE_URL; -env RAILS_LOG_TO_STDOUT; -env REDIS_HOST; -env SECRET_KEY_BASE; -env SETTINGS__BULKRAX__ENABLED; -env SETTINGS__ACTIVE_JOB__QUEUE_ADAPTER; -env SETTINGS__FITS_PATH; -env SETTINGS__MULTITENANCY__ADMIN_HOST; -env SETTINGS__MULTITENANCY__ADMIN_ONLY_TENANT_CREATION; -env SETTINGS__MULTITENANCY__DEFAULT_HOST; -env SETTINGS__MULTITENANCY__ENABLED; -env SETTINGS__SOLR__URL; -env SOLR_URL; \ No newline at end of file diff --git a/ops/helm.yaml b/ops/helm.yaml deleted file mode 100644 index ef516ec2a..000000000 --- a/ops/helm.yaml +++ /dev/null @@ -1,3 +0,0 @@ -extraEnvVars: - - name: CONFDIR - value: /app/samvera/hyrax-webapp/solr/config diff --git a/ops/nginx.sh b/ops/nginx.sh deleted file mode 100755 index 737c68509..000000000 --- a/ops/nginx.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -e -if [[ ! -e /var/log/nginx/error.log ]]; then - # The Nginx log forwarder might be sleeping and waiting - # until the error log becomes available. We restart it in - # 1 second so that it picks up the new log file quickly. - (sleep 1 && sv restart /etc/service/nginx-log-forwarder) -fi - -if [ -z $PASSENGER_APP_ENV ] -then - export PASSENGER_APP_ENV=development -fi - -if [[ $PASSENGER_APP_ENV == "development" ]] || [[ $PASSENGER_APP_ENV == "test" ]] -then - # this should be a volume in dev, it makes rails assets much faster - /bin/bash -l -c 'chown -fR app:app /app/samvera/hyrax-webapp/tmp/cache' - /sbin/setuser app /bin/bash -l -c 'cd /app/samvera/hyrax-webapp && bundle exec rails db:test:prepare' -fi - -if [[ $PASSENGER_APP_ENV == "production" ]] || [[ $PASSENGER_APP_ENV == "staging" ]] -then - /bin/bash -l -c 'chown -fR app:app /app/samvera/hyrax-webapp/public/assets' # mounted volume may have wrong permissions - /sbin/setuser app /bin/bash -l -c 'cd /app/samvera/hyrax-webapp && rsync -a public/assets-new/ public/assets/' -fi - -exec /usr/sbin/nginx diff --git a/ops/review-deploy.tmpl.yaml b/ops/review-deploy.tmpl.yaml index 46d396462..fb855426d 100644 --- a/ops/review-deploy.tmpl.yaml +++ b/ops/review-deploy.tmpl.yaml @@ -12,7 +12,7 @@ derivativesVolume: uploadsVolume: storageClass: nfs -extraVolumeMounts: +extraVolumeMounts: &volMounts - name: uploads mountPath: /app/samvera/hyrax-webapp/tmp/imports subPath: imports @@ -39,13 +39,11 @@ ingress: paths: - path: / -extraEnvVars: - - name: SETTINGS__MULTITENANCY__ADMIN_HOST +extraEnvVars: &envVars + - name: HYKU_ADMIN_HOST value: hyku-$CI_MERGE_REQUEST_ID.example.com - - name: SETTINGS__MULTITENANCY__ROOT_HOST + - name: HYKU_ROOT_HOST value: hyku-$CI_MERGE_REQUEST_ID.example.com - - name: SETTINGS__MULTITENANCY__DEFAULT_HOST - value: "%{tenant}.hyku-$CI_MERGE_REQUEST_ID.example.com" - name: CONFDIR value: "/app/samvera/hyrax-webapp/solr/config" - name: INITIAL_ADMIN_EMAIL @@ -74,16 +72,12 @@ extraEnvVars: value: samvera@example.com - name: SETTINGS__FITS_PATH value: /app/fits/fits.sh - - name: SETTINGS__MULTITENANCY__ADMIN_ONLY_TENANT_CREATION + - name: HYKU_ADMIN_ONLY_TENANT_CREATION value: "true" - - name: SETTINGS__MULTITENANCY__DEFAULT_HOST + - name: HYKU_DEFAULT_HOST value: "%{tenant}.hyku-staging.example.com" - - name: SETTINGS__MULTITENANCY__ENABLED + - name: HYKU_ENABLED value: "true" - - name: SETTINGS__SOLR__COLLECTION_OPTIONS__COLLECTION__CONFIG_NAME - value: $CI_COMMIT_SHORT_SHA - - name: SETTINGS__SOLR__CONFIGSET - value: $CI_COMMIT_SHORT_SHA - name: SOLR_ADMIN_USER value: admin - name: SOLR_COLLECTION_NAME @@ -112,87 +106,8 @@ worker: runAsGroup: 101 fsGroup: 101 fsGroupChangePolicy: "OnRootMismatch" - extraVolumeMounts: - - name: uploads - mountPath: /app/samvera/hyrax-webapp/tmp/imports - subPath: imports - - name: uploads - mountPath: /app/samvera/hyrax-webapp/tmp/exports - subPath: exports - - name: uploads - mountPath: /app/samvera/hyrax-webapp/public/system - subPath: public-system - - name: uploads - mountPath: /app/samvera/hyrax-webapp/public/uploads - subPath: public-uploads - - name: uploads - mountPath: /app/samvera/hyrax-webapp/tmp/network_files - subPath: network-files - extraEnvVars: - - name: SETTINGS__MULTITENANCY__ADMIN_HOST - value: hyku-$CI_MERGE_REQUEST_ID.example.com - - name: SETTINGS__MULTITENANCY__ROOT_HOST - value: hyku-$CI_MERGE_REQUEST_ID.example.com - - name: SETTINGS__MULTITENANCY__DEFAULT_HOST - value: "%{tenant}.hyku-$CI_MERGE_REQUEST_ID.example.com" - - name: CONFDIR - value: "/app/samvera/hyrax-webapp/solr/config" - - name: INITIAL_ADMIN_EMAIL - value: samvera@example.com - - name: INITIAL_ADMIN_PASSWORD - value: testing123 - - name: IN_DOCKER - value: "true" - - name: LD_LIBRARY_PATH - value: /app/fits/tools/mediainfo/linux - - name: PASSENGER_APP_ENV - value: production - - name: RAILS_ENV - value: production - - name: RAILS_LOG_TO_STDOUT - value: "true" - - name: RAILS_MAX_THREADS - value: "5" - - name: RAILS_SERVE_STATIC_FILES - value: "true" - - name: SETTINGS__ACTIVE_JOB__QUEUE_ADAPTER - value: sidekiq - - name: SETTINGS__CONTACT_EMAIL - value: samvera@example.com - - name: SETTINGS__DEVISE__INVITATION_FROM_EMAIL - value: samvera@example.com - - name: SETTINGS__FITS_PATH - value: /app/fits/fits.sh - - name: SETTINGS__MULTITENANCY__ADMIN_ONLY_TENANT_CREATION - value: "true" - - name: SETTINGS__MULTITENANCY__DEFAULT_HOST - value: "%{tenant}.hyku-staging.example.com" - - name: SETTINGS__MULTITENANCY__ENABLED - value: "true" - - name: SETTINGS__SOLR__COLLECTION_OPTIONS__COLLECTION__CONFIG_NAME - value: $CI_COMMIT_SHORT_SHA - - name: SETTINGS__SOLR__CONFIGSET - value: $CI_COMMIT_SHORT_SHA - - name: SOLR_ADMIN_USER - value: admin - - name: SOLR_COLLECTION_NAME - value: hyrax - - name: SOLR_CONFIGSET_NAME - value: $CI_COMMIT_SHORT_SHA - - name: SMTP_ENABLED - value: "true" - - name: SMTP_USER_NAME - value: fake - - name: SMTP_PASSWORD - value: fake - - name: SMTP_ADDRESS - value: fake - - name: SMTP_DOMAIN - value: fake - - name: SMTP_PORT - value: "2525" - - name: SMTP_TYPE - value: cram_md5 + extraVolumeMounts: *volMounts + extraEnvVars: *envVars podSecurityContext: runAsUser: 1001 diff --git a/ops/webapp.conf b/ops/webapp.conf deleted file mode 100644 index 9f513e18c..000000000 --- a/ops/webapp.conf +++ /dev/null @@ -1,16 +0,0 @@ -server { - listen 80; - server_name _; - root /app/samvera/hyrax-webapp/public; - client_body_in_file_only clean; - client_body_buffer_size 32K; - - client_max_body_size 0; - - sendfile on; - send_timeout 300s; - # The following deploys your Ruby/Python/Node.js/Meteor app on Passenger. - passenger_enabled on; - passenger_user app; - passenger_max_requests 5; -} diff --git a/spec/controllers/account_sign_up_controller_spec.rb b/spec/controllers/account_sign_up_controller_spec.rb index f061e66d8..ce20e70b7 100644 --- a/spec/controllers/account_sign_up_controller_spec.rb +++ b/spec/controllers/account_sign_up_controller_spec.rb @@ -7,6 +7,19 @@ sign_in user if user end + # rubocop:disable RSpec/BeforeAfterAll + before(:all) do + @multitenant = ENV['HYKU_MULTITENANT'] + ENV['HYKU_MULTITENANT'] = 'true' + Rails.application.reload_routes! + end + + after(:all) do + ENV['HYKU_MUTLITENANT'] = @multitenant # rubocop:disable RSpec/InstanceVariable + Rails.application.reload_routes! + end + # rubocop:enable RSpec/BeforeAfterAll + # This should return the minimal set of attributes required to create a valid # Account. As you add validations to Account, be sure to # adjust the attributes here as well. @@ -20,7 +33,8 @@ context 'with access' do before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(false) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION', false).and_return(false) end describe "GET #new" do @@ -41,7 +55,7 @@ expect do post :create, params: { account: valid_attributes } end.to change(Account, :count).by(1) - expect(assigns(:account).cname).to be_cname('x') + expect(assigns(:account).cname).to eq('x.test.host') expect(assigns(:account).errors).to be_empty expect do # now repeat the same action @@ -69,7 +83,8 @@ context 'without access' do before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(true) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION', false).and_return(true) end describe "GET #new" do @@ -91,7 +106,8 @@ let(:user) { FactoryBot.create(:admin) } before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(true) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION', false).and_return(true) end describe "GET #new" do @@ -112,7 +128,7 @@ post :create, params: { account: valid_attributes } end.to change(Account, :count).by(1) - expect(assigns(:account).cname).to be_cname('x') + expect(assigns(:account).cname).to eq('x.test.host') expect(assigns(:account).errors).to be_empty end end diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb index 2f91253f6..e5e5058bf 100644 --- a/spec/controllers/admin/accounts_controller_spec.rb +++ b/spec/controllers/admin/accounts_controller_spec.rb @@ -43,7 +43,7 @@ put :update, params: { account: new_attributes } account.reload expect(account.cname).to eq 'new.example.com' - expect(response).to redirect_to(edit_admin_account_path) + expect(response).to redirect_to(edit_admin_account_path(account)) end it "assigns the requested account as @account" do diff --git a/spec/controllers/contacts_controller_spec.rb b/spec/controllers/contacts_controller_spec.rb deleted file mode 100644 index 5d0121c5f..000000000 --- a/spec/controllers/contacts_controller_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe ContactsController, type: :controller do - before do - sign_in user - end - - let(:valid_attributes) do - { - contact_email: 'test@example.com' - } - end - - let(:invalid_attributes) do - { contact_email: nil } - end - - context 'with an unprivileged user' do - let(:user) { FactoryBot.create(:user) } - - describe "GET #edit" do - it "denies the request" do - get :edit - expect(response).to have_http_status(:unauthorized) - end - end - - describe "PUT #update" do - it "denies the request" do - put :update, params: { site: valid_attributes } - expect(response).to have_http_status(:unauthorized) - end - end - end - - context 'with an administrator' do - let(:user) { FactoryBot.create(:admin) } - - describe "GET #edit" do - it "assigns the requested site as @site" do - get :edit, params: {} - expect(assigns(:site)).to eq(Site.instance) - end - end - - describe "PUT #update" do - context "with valid params" do - let(:new_attributes) do - { - contact_email: 'new@test.com' - } - end - - it "updates the requested site" do - put :update, params: { site: new_attributes } - Site.reload - expect(Site.contact_email).to eq "new@test.com" - end - - it "assigns the requested site as @site" do - put :update, params: { site: valid_attributes } - expect(assigns(:site)).to eq(Site.instance) - end - - it "redirects to the site" do - put :update, params: { site: valid_attributes } - expect(response).to redirect_to(edit_site_contact_path) - end - end - - context "with invalid params" do - it "assigns the site as @site" do - put :update, params: { site: invalid_attributes } - expect(assigns(:site)).to eq(Site.instance) - end - - it "redirects to the 'edit' template" do - put :update, params: { site: invalid_attributes } - expect(response).to redirect_to(edit_site_contact_path) - end - end - end - end -end diff --git a/spec/controllers/hyku/registrations_controller_spec.rb b/spec/controllers/hyku/registrations_controller_spec.rb index 461db07a9..3de87f559 100644 --- a/spec/controllers/hyku/registrations_controller_spec.rb +++ b/spec/controllers/hyku/registrations_controller_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Hyku::RegistrationsController, type: :controller do before do - allow(Settings.devise).to receive(:account_signup).and_return(account_signup_enabled) + allow_any_instance_of(Account).to receive(:allow_signup).and_return(account_signup_enabled) # Recommended by Devise: https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-%28and-RSpec%29 @request.env['devise.mapping'] = Devise.mappings[:user] end diff --git a/spec/features/accounts_spec.rb b/spec/features/accounts_spec.rb index 3aa5e685e..63ac29df4 100644 --- a/spec/features/accounts_spec.rb +++ b/spec/features/accounts_spec.rb @@ -25,6 +25,7 @@ end it 'changes the associated cname' do + pending "adjust for domain names instead of single cname" visit edit_proprietor_account_path(account) fill_in 'Tenant CNAME', with: 'example.com' diff --git a/spec/features/admin_dashboard_spec.rb b/spec/features/admin_dashboard_spec.rb index 30f7570b5..ad0a0b13c 100644 --- a/spec/features/admin_dashboard_spec.rb +++ b/spec/features/admin_dashboard_spec.rb @@ -34,7 +34,6 @@ expect(page).to have_link('Settings') # Need to click link to open collapsed menu click_link "Settings" - expect(page).to have_link('Contact') expect(page).to have_link('Labels') expect(page).to have_link('Appearance') expect(page).to have_link('Collection Types') diff --git a/spec/features/contact_spec.rb b/spec/features/contact_spec.rb deleted file mode 100644 index 40d6afe85..000000000 --- a/spec/features/contact_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe 'Site contact configuration' do - context 'as an administrator' do - let(:user) { FactoryBot.create(:admin) } - - before do - login_as(user, scope: :user) - end - - describe 'contact_email' do - it 'updates the contact_email' do - visit edit_site_contact_path - fill_in 'Contact email', with: 'contact@email.com' - click_on 'Save' - expect(page).to have_current_path(edit_site_contact_path(locale: 'en')) - expect(page).to have_field('Contact email') - # used eq rather than be to compare value rather than the object itself - expect(page.first(:css, "#site_contact_email")[:value]).to eq "contact@email.com" - end - end - end -end diff --git a/spec/features/splash_spec.rb b/spec/features/splash_spec.rb index 608f83cbd..a6cbfbbd6 100644 --- a/spec/features/splash_spec.rb +++ b/spec/features/splash_spec.rb @@ -2,10 +2,13 @@ RSpec.describe "The splash page", multitenant: true do around do |example| + original = ENV['HYKU_ADMIN_ONLY_TENANT_CREATION'] + ENV['HYKU_ADMIN_ONLY_TENANT_CREATION'] = "true" default_host = Capybara.default_host Capybara.default_host = Capybara.app_host || "http://#{Account.admin_host}" example.run Capybara.default_host = default_host + ENV['HYKU_ADMIN_ONLY_TENANT_CREATION'] = original end it "shows the page, displaying the Hyku version" do diff --git a/spec/jobs/create_solr_collection_job_spec.rb b/spec/jobs/create_solr_collection_job_spec.rb index ff9b786d7..bbe2721ae 100644 --- a/spec/jobs/create_solr_collection_job_spec.rb +++ b/spec/jobs/create_solr_collection_job_spec.rb @@ -19,7 +19,7 @@ 'collection.configName': 'hyku')) described_class.perform_now(account) - expect(account.solr_endpoint.url).to eq "#{Settings.solr.url}#{account.tenant}" + expect(account.solr_endpoint.url).to eq "#{ENV.fetch('SOLR_URL')}#{account.tenant}" end it 'is idempotent' do diff --git a/spec/lib/active_job/queue_adapters/better_active_elastic_job_adapter_spec.rb b/spec/lib/active_job/queue_adapters/better_active_elastic_job_adapter_spec.rb index c37b0ecd5..94140ae0d 100644 --- a/spec/lib/active_job/queue_adapters/better_active_elastic_job_adapter_spec.rb +++ b/spec/lib/active_job/queue_adapters/better_active_elastic_job_adapter_spec.rb @@ -9,7 +9,8 @@ let(:job) { CreateSolrCollectionJob.new(account) } before do - allow(Settings.active_job_queue).to receive(:url).and_return(queue_url) + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with('HYKU_ACTIVE_JOB_QUEUE_URL').and_return(queue_url) Rails.application.config.active_elastic_job.secret_key_base = Rails.application.secrets[:secret_key_base] allow(described_class).to receive(:aws_sqs_client).and_return(aws_sqs_client) end diff --git a/spec/mailers/hyrax/contact_mailer_spec.rb b/spec/mailers/hyrax/contact_mailer_spec.rb index b0ec1f33c..ab792372b 100644 --- a/spec/mailers/hyrax/contact_mailer_spec.rb +++ b/spec/mailers/hyrax/contact_mailer_spec.rb @@ -3,6 +3,7 @@ require 'rails_helper' RSpec.describe Hyrax::ContactMailer, type: :mailer do + let(:account) { FactoryBot.create(:account) } let(:contact_form) do Hyrax::ContactForm.new( email: 'test@example.com', @@ -17,6 +18,7 @@ let(:mail) { described_class.contact(contact_form) } it "renders the body" do + allow(Site).to receive(:account).and_return(account) expect(mail.body.encoded).to match(/Test Tester/) end end diff --git a/spec/models/account_cross_search_spec.rb b/spec/models/account_cross_search_spec.rb new file mode 100644 index 000000000..a5d9bcc9f --- /dev/null +++ b/spec/models/account_cross_search_spec.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe AccountCrossSearch, type: :model do + it do + is_expected.to belong_to(:full_account) + .class_name('Account') + + is_expected.to belong_to(:search_account) + .class_name('Account') + end +end diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index d2ea29028..3f8e94c07 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -53,7 +53,8 @@ end it 'returns canonicalized value' do - allow(Settings.multitenancy).to receive(:default_host).and_return("%{tenant}.DEMO.hydrainabox.org.") + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_DEFAULT_HOST', anything).and_return("%{tenant}.DEMO.hydrainabox.org.") expect(described_class.default_cname('foobar')).to eq 'foobar.demo.hydrainabox.org' expect(described_class.default_cname('fooBAR')).to eq 'foobar.demo.hydrainabox.org' expect(described_class.default_cname('ONE.two.3')).to eq 'one-two-3.demo.hydrainabox.org' @@ -70,18 +71,23 @@ describe '.admin_host' do it 'uses the configured setting' do - allow(Settings.multitenancy).to receive(:admin_host).and_return('admin-host') + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_HOST', anything).and_return('admin-host') expect(described_class.admin_host).to eq 'admin-host' end it 'falls back to the HOST environment variable' do - allow(Settings.multitenancy).to receive(:admin_host).and_return(nil) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_HOST', anything).and_return(nil) + allow(ENV).to receive(:[]).and_call_original allow(ENV).to receive(:[]).with('HOST').and_return('system-host') expect(described_class.admin_host).to eq 'system-host' end it 'falls back to localhost' do - allow(Settings.multitenancy).to receive(:admin_host).and_return(nil) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_HOST', anything).and_return(nil) + allow(ENV).to receive(:[]).and_call_original allow(ENV).to receive(:[]).with('HOST').and_return(nil) expect(described_class.admin_host).to eq 'localhost' end @@ -124,7 +130,7 @@ it "reverts to using file store when cache is off" do account.settings[:cache_api] = false account.switch! - expect(Rails.application.config.cache_store).to eq([:file_store, nil]) + expect(Rails.application.config.cache_store).to eq([:file_store, "/app/samvera/file_cache"]) end end @@ -134,7 +140,7 @@ it "uses the file store" do expect(Rails.application.config.action_controller.perform_caching).to be_falsey expect(ActionController::Base.perform_caching).to be_falsey - expect(Rails.application.config.cache_store).to eq([:file_store, nil]) + expect(Rails.application.config.cache_store).to eq([:file_store, "/app/samvera/file_cache"]) end end @@ -158,7 +164,7 @@ describe '#switch' do let!(:previous_solr_url) { ActiveFedora::SolrService.instance.conn.uri.to_s } - let!(:previous_redis_namespace) { 'hyku' } + let!(:previous_redis_namespace) { 'hyrax' } let!(:previous_fedora_host) { ActiveFedora.fedora.host } let!(:previous_data_cite_mode) { Hyrax::DOI::DataCiteRegistrar.mode } let!(:previous_data_cite_prefix) { Hyrax::DOI::DataCiteRegistrar.prefix } @@ -267,20 +273,25 @@ context 'is set' do it 'builds default cname from name and default_host' do - allow(Settings.multitenancy).to receive(:default_host).and_return "%{tenant}.dev" + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_DEFAULT_HOST', anything).and_return("%{tenant}.dev") expect(account1.errors).to be_empty expect(account1.domain_names.first.cname).to eq('example.dev') end end context 'is unset' do + around do |example| + default = ENV['HYKU_DEFAULT_TENANT'] + example.run + ENV['HYKU_DEFAULT_TENANT'] = default + end + it 'builds default cname from name and admin_host' do - original = Settings.multitenancy.default_host - Settings.multitenancy.default_host = nil - allow(Settings.multitenancy).to receive(:admin_host).and_return('admin-host') + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_HOST', anything).and_return('admin-host') expect(account1.errors).to be_empty expect(account1.domain_names.first.cname).to eq('example.admin-host') - Settings.multitenancy.default_host = original end end end @@ -372,7 +383,8 @@ context 'single tenant in production environment' do before do - allow(Settings.multitenancy).to receive(:enabled).and_return false + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_MULTITENANT', anything).and_return(false) allow(Rails.env).to receive(:test?).and_return false end @@ -381,7 +393,8 @@ context 'default tenant in a multitenant production environment' do before do - allow(Settings.multitenancy).to receive(:enabled).and_return true + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_MULTITENANT', anything).and_return(true) allow(Rails.env).to receive(:test?).and_return false allow(Apartment::Tenant).to receive(:current_tenant).and_return Apartment::Tenant.default_tenant end @@ -530,4 +543,41 @@ end end end + + describe 'cross tenant shared search' do + context 'settings keys' do + it 'has default value for #shared_search' do + expect(account.search_only).to eq false + end + end + + context 'boolean method checks' do + it '#shared_search_tenant? defaults to false' do + expect(account).not_to be_search_only + end + end + + context 'can add and remove Full Account from shared search' do + let(:normal_account) { create(:account) } + let(:cross_search_solr) { create(:solr_endpoint, url: "http://solr:8983/solr/hydra-cross-search-tenant") } + + let(:shared_search_account) do + create(:account, + search_only: true, + full_account_ids: [normal_account.id], + solr_endpoint: cross_search_solr, + fcrepo_endpoint: nil) + end + + it 'contains full_account' do + expect(shared_search_account.full_accounts).to be_truthy + expect(shared_search_account.full_accounts.size).to eq 1 + end + + it 'removes full_account' do + shared_search_account.full_account_ids = [] + expect(shared_search_account.full_accounts.size).to eq 0 + end + end + end end diff --git a/spec/models/hyrax/contact_form_spec.rb b/spec/models/hyrax/contact_form_spec.rb index 8ecb37f2d..bf5bf53ce 100644 --- a/spec/models/hyrax/contact_form_spec.rb +++ b/spec/models/hyrax/contact_form_spec.rb @@ -9,23 +9,26 @@ from: "from@email.com" ) end - - allow(Settings).to receive(:contact_email_to).and_return('hyrax@email.com') end context 'no email set' do before do - site = double(Site.new, contact_email: '') + site = double(Site.new) + account = Account.new allow(Site).to receive(:instance).and_return(site) + allow(Site).to receive(:account).and_return(account) end it 'uses the hyrax setting' do - expect(subject.headers[:to]).to eq('hyrax@email.com') + expect(subject.headers[:to]).to eq('change-me-in-settings@example.com') end end context 'site email set' do before do - site = double(Site.new, contact_email: 'setting@email.com') + site = double(Site.new) + account = Account.new + account.contact_email_to = 'setting@email.com' allow(Site).to receive(:instance).and_return(site) + allow(Site).to receive(:account).and_return(account) end it 'uses the Site email' do expect(subject.headers[:to]).to eq('setting@email.com') diff --git a/spec/models/uploaded_file_spec.rb b/spec/models/uploaded_file_spec.rb index af68bf74f..65767a785 100644 --- a/spec/models/uploaded_file_spec.rb +++ b/spec/models/uploaded_file_spec.rb @@ -31,7 +31,7 @@ end describe CarrierWave::Storage::File do # default in dev/test - before { expect(Hyrax::UploadedFileUploader).to receive(:storage).and_return(described_class) } + before { expect(Hyrax::UploadedFileUploader).to receive(:storage).and_return(described_class).at_least(:once) } it_behaves_like 'Regular upload' it 'returns a SanitizedFile' do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index cfdb71152..ef319921e 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -5,10 +5,11 @@ # In test most, unset some variables that can cause trouble # before booting up Rails -ENV['SETTINGS__MULTITENANCY__ADMIN_HOST'] = nil -ENV['SETTINGS__MULTITENANCY__ADMIN_ONLY_TENANT_CREATION'] = nil -ENV['SETTINGS__MULTITENANCY__DEFAULT_HOST'] = nil -ENV['SETTINGS__MULTITENANCY__ENABLED'] = nil +ENV['HYKU_ADMIN_HOST'] = 'test.host' +ENV['HYKU_ROOT_HOST'] = 'test.host' +ENV['HYKU_ADMIN_ONLY_TENANT_CREATION'] = nil +ENV['HYKU_DEFAULT_HOST'] = nil +ENV['HYKU_MULTITENANT'] = 'true' require 'simplecov' SimpleCov.start('rails') @@ -58,6 +59,8 @@ Capybara.default_max_wait_time = 8 Capybara.default_driver = :rack_test +ENV['WEB_HOST'] ||= `hostname -s`.strip + if ENV['CHROME_HOSTNAME'].present? capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( chromeOptions: { @@ -79,11 +82,6 @@ end Capybara.server_host = '0.0.0.0' Capybara.server_port = 3001 - ENV['WEB_HOST'] ||= if ENV['IN_DOCKER'] - 'web' - else - `hostname -s`.strip - end Capybara.app_host = "http://#{ENV['WEB_HOST']}:#{Capybara.server_port}" else capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( @@ -143,6 +141,8 @@ DatabaseCleaner.clean_with(:truncation) Account.destroy_all CreateSolrCollectionJob.new.without_account('hydra-test') if ENV['IN_DOCKER'] + CreateSolrCollectionJob.new.without_account('hydra-sample') + CreateSolrCollectionJob.new.without_account('hydra-cross-search-tenant', 'hydra-test, hydra-sample') end config.before do |example| diff --git a/spec/requests/catalog_controller_spec.rb b/spec/requests/catalog_controller_spec.rb new file mode 100644 index 000000000..818b80bd3 --- /dev/null +++ b/spec/requests/catalog_controller_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe CatalogController, type: :request, clean: true, multitenant: true do + let(:user) { create(:user, email: 'test_user@repo-sample.edu') } + let(:work) { build(:work, title: ['welcome test'], id: SecureRandom.uuid, user: user) } + let(:hyku_sample_work) { build(:work, title: ['sample test'], id: SecureRandom.uuid, user: user) } + let(:sample_solr_connection) { RSolr.connect url: "#{ENV['SOLR_URL']}hydra-sample" } + + let(:cross_search_solr) { create(:solr_endpoint, url: "#{ENV['SOLR_URL']}hydra-cross-search-tenant") } + let!(:cross_search_tenant_account) do + create(:account, + name: 'cross_search', + cname: 'example.com', + solr_endpoint: cross_search_solr, + fcrepo_endpoint: nil) + end + + before do + WebMock.disable! + allow(AccountElevator).to receive(:switch!).with(cross_search_tenant_account.cname).and_return('public') + allow(Apartment::Tenant.adapter).to receive(:connect_to_new).and_return('') + ActiveFedora::SolrService.instance.conn = sample_solr_connection + ActiveFedora::SolrService.add(hyku_sample_work.to_solr) + ActiveFedora::SolrService.commit + + ActiveFedora::SolrService.reset! + ActiveFedora::SolrService.add(work.to_solr) + ActiveFedora::SolrService.commit + end + + after do + WebMock.enable! + + ActiveFedora::SolrService.instance.conn = sample_solr_connection + ActiveFedora::SolrService.delete(hyku_sample_work.id) + ActiveFedora::SolrService.commit + + ActiveFedora::SolrService.reset! + ActiveFedora::SolrService.delete(work.id) + ActiveFedora::SolrService.commit + end + + describe 'Cross Tenant Search' do + let(:cross_tenant_solr_options) do + { + "read_timeout" => 120, + "open_timeout" => 120, + "url" => "#{ENV['SOLR_URL']}hydra-cross-search-tenant", + "adapter" => "solr" + } + end + + let(:black_light_config) { Blacklight::Configuration.new(connection_config: cross_tenant_solr_options) } + + before do + host! "http://#{cross_search_tenant_account.cname}/" + end + + context 'can fetch data from other tenants' do + it 'cross-search-tenant can fetch all record in child tenants' do + connection = RSolr.connect(url: "#{ENV['SOLR_URL']}hydra-cross-search-tenant") + allow_any_instance_of(Blacklight::Solr::Repository).to receive(:build_connection).and_return(connection) + allow(CatalogController).to receive(:blacklight_config).and_return(black_light_config) + + # get '/catalog', params: { q: '*' } + # get search_catalog_url, params: { locale: 'en', q: 'test' } + get "http://#{cross_search_tenant_account.cname}/catalog?q=test" # , params: { q: 'test' } + expect(response.status).to eq(200) + end + end + end +end diff --git a/spec/routing/contact_routing_spec.rb b/spec/routing/contact_routing_spec.rb deleted file mode 100644 index 5b70a03b9..000000000 --- a/spec/routing/contact_routing_spec.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe ContactsController, type: :routing do - describe "routing" do - it "routes to #edit" do - expect(get: "/site/contact/edit").to route_to("contacts#edit") - end - it "routes to #update via PUT" do - expect(put: "/site/contact").to route_to("contacts#update") - end - - it "routes to #update via PATCH" do - expect(patch: "/site/contact").to route_to("contacts#update") - end - end -end diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index dc79f230e..4bac83570 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -8,9 +8,9 @@ end RSpec::Matchers.define :be_cname do |subdomain| - target_cname = if Settings.multitenancy.default_host.present? + target_cname = if ENV['HYKU_DEFAULT_HOST'].present? # rubocop:disable Style/FormatStringToken - Settings.multitenancy.default_host.gsub('%{tenant}', subdomain) + ENV['HYKU_DEFAULT_HOST'].gsub('%{tenant}', subdomain) # rubocop:enable Style/FormatStringToken else "#{subdomain}.localhost" diff --git a/spec/support/multitenancy_metadata.rb b/spec/support/multitenancy_metadata.rb index 61838e0e2..c57fd209d 100644 --- a/spec/support/multitenancy_metadata.rb +++ b/spec/support/multitenancy_metadata.rb @@ -1,15 +1,8 @@ # frozen_string_literal: true RSpec.configure do |config| - # The before and after blocks must run instantaneously, because Capybara + # The around blocks must run instantaneously, because Capybara # might not actually be used in all examples where it's included. - config.after do - example = RSpec.current_example - if example.metadata[:multitenant] || example.metadata[:singletenant] - allow(Settings.multitenancy).to receive(:enabled).and_call_original - Rails.application.reload_routes! - end - end # There are 3 optional flags available to a test block. Only ONE will be active # at any given time. They are (with areas of likely use): @@ -23,26 +16,44 @@ # :controller - default to :faketenant, since most resource controllers can be tested # without routing as long as they get some account. - config.before do - example = RSpec.current_example + config.before do |example| + if !example.metadata[:multitenant] && !example.metadata[:singletenant] + if example.metadata[:faketenant] || example.metadata[:type] == :controller + example.metadata[:faketenant] = true if example.metadata[:type] == :controller # flag for cleanup later + acct = FactoryBot.build(:account, tenant: 'FakeTenant', cname: 'tenant1') + allow(acct).to receive(:persisted?).and_return true # nevertheless + allow(Account).to receive(:from_request).and_return(acct) + end + end + end + + config.around do |example| + @multitenat = ENV['HYKU_MULTITENANT'] + @admin_host = ENV['HYKU_ADMIN_HOST'] + @default_host = ENV['HYKU_DEFAULT_HOST'] + if example.metadata[:multitenant] - allow(Settings.multitenancy).to receive(:enabled).and_return(true) + ENV['HYKU_MULTITENANT'] = "true" if ENV['WEB_HOST'] - Settings.multitenancy.admin_host = ENV['WEB_HOST'] + ENV['HYKU_ADMIN_HOST'] = ENV['WEB_HOST'] # rubocop:disable Style/FormatStringToken - Settings.multitenancy.default_host = "%{tenant}.#{ENV['WEB_HOST']}" + ENV['HYKU_DEFAULT_HOST'] = "%{tenant}.#{ENV['WEB_HOST']}" # rubocop:enable Style/FormatStringToken end Rails.application.reload_routes! elsif example.metadata[:singletenant] || example.metadata[:type] == :feature example.metadata[:singletenant] = true if example.metadata[:type] == :feature # flag for cleanup later - allow(Settings.multitenancy).to receive(:enabled).and_return(false) + ENV['HYKU_MULTITENANT'] = "false" + Rails.application.reload_routes! + end + + example.run + + if example.metadata[:multitenant] || example.metadata[:singletenant] + ENV['HYKU_MULTITENANT'] = @multitenat + ENV['HYKU_ADMIN_HOST'] = @admin_host + ENV['HYKU_DEFAULT_HOST'] = @default_host Rails.application.reload_routes! - elsif example.metadata[:faketenant] || example.metadata[:type] == :controller - example.metadata[:faketenant] = true if example.metadata[:type] == :controller # flag for cleanup later - acct = FactoryBot.build(:account, tenant: 'FakeTenant', cname: 'tenant1') - allow(acct).to receive(:persisted?).and_return true # nevertheless - allow(Account).to receive(:from_request).and_return(acct) end end end diff --git a/spec/support/shared_examples_for_csv_importer.rb b/spec/support/shared_examples_for_csv_importer.rb index b8ac6a134..03b2ab9be 100644 --- a/spec/support/shared_examples_for_csv_importer.rb +++ b/spec/support/shared_examples_for_csv_importer.rb @@ -11,7 +11,9 @@ end let(:factory) { described_class.new(attributes, File.join(fixture_path, 'images')) } - before { factory.run } + before do + factory.run + end describe "#run" do it "uploads the content of the file" do diff --git a/spec/system/edit_account_spec.rb b/spec/system/edit_account_spec.rb new file mode 100644 index 000000000..abe1432a2 --- /dev/null +++ b/spec/system/edit_account_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Proprietor Edit Account Page', type: :system do + let(:user) { FactoryBot.create(:admin) } + let(:full_account) { create(:account) } + let!(:account) { create(:account, search_only: true, full_account_ids: [full_account.id]) } + + before do + driven_by(:rack_test) + login_as(user, scope: :user) + + Capybara.default_host = "http://#{account.cname}" + end + + describe 'shared search checkbox' do + xit 'can display checkbox for shared_search' do + visit "/proprietor/accounts/#{account.id}/edit?locale=en" + expect(find_field(id: 'account_search_only')).to be_checked + expect(page).to have_content('Search only') + end + + xit 'can display add to account text' do + visit "/proprietor/accounts/#{account.id}/edit?locale=en" + expect(page).to have_content('Add account to search') + end + end +end diff --git a/spec/system/new_account_spec.rb b/spec/system/new_account_spec.rb new file mode 100644 index 000000000..dcd6b550a --- /dev/null +++ b/spec/system/new_account_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Proprietor New Account Page', type: :system do + let(:user) { FactoryBot.create(:admin) } + let(:full_account) { create(:account) } + let!(:account) { create(:account, search_only: true) } + + before do + driven_by(:rack_test) + login_as(user, scope: :user) + Capybara.default_host = "http://#{account.cname}" + end + + describe 'shared search checkbox' do + xit 'can display checkbox for shared_search' do + visit '/proprietor/accounts/new?locale=en' + expect(page).to have_content('Search only') + expect(find_field(id: 'account_search_only')).not_to be_checked + end + + xit 'can check shared_search checkbox' do + visit '/proprietor/accounts/new?locale=en' + check 'account_search_only' + expect(find_field(id: 'account_search_only')).to be_checked + end + + xit 'can display add to account text' do + visit '/proprietor/accounts/new?locale=en' + check 'account_search_only' + expect(page).to have_content('Add account to search') + end + end +end diff --git a/spec/views/splash/index.html.erb_spec.rb b/spec/views/splash/index.html.erb_spec.rb index ac71c53d4..b81a7326c 100644 --- a/spec/views/splash/index.html.erb_spec.rb +++ b/spec/views/splash/index.html.erb_spec.rb @@ -7,7 +7,8 @@ context 'Anonymous or non-Admin user with admin_only_tenant_creation=false' do before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(false) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION').and_return(false) allow(controller).to receive(:can?).with(:manage, Account).and_return(false) render end @@ -20,7 +21,8 @@ context 'Admin user with admin_only_tenant_creation=true' do before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(true) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION', nil).and_return(true) allow(controller).to receive(:can?).with(:manage, Account).and_return(true) allow(controller).to receive(:user_signed_in?).and_return(true) render @@ -34,7 +36,9 @@ context 'Anonymous user with admin_only_tenant_creation=true' do before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(true) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION', false).and_return(true) + allow(controller).to receive(:can?).with(:manage, Account).and_return(false) allow(controller).to receive(:user_signed_in?).and_return(false) render @@ -48,7 +52,8 @@ context 'Authenticated, non-Admin user with admin_only_tenant_creation=true' do before do - allow(Settings.multitenancy).to receive(:admin_only_tenant_creation).and_return(true) + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with('HYKU_ADMIN_ONLY_TENANT_CREATION', false).and_return(true) allow(controller).to receive(:can?).with(:manage, Account).and_return(false) allow(controller).to receive(:user_signed_in?).and_return(true) render