diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a2c25b90d..13fc15d1f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -96,7 +96,13 @@ def job_status private - def feature_enabled?(feature = controller_name) + def feature_enabled?(feature) + Space.current_space.feature_enabled?(feature) + end + + helper_method :feature_enabled? + + def ensure_feature_enabled(feature = controller_name) if TeSS::Config.feature.key?(feature) && !TeSS::Config.feature[feature] raise ActionController::RoutingError.new('Feature not enabled') end diff --git a/app/controllers/bioschemas_controller.rb b/app/controllers/bioschemas_controller.rb index d80f2ebd1..dd0719bde 100644 --- a/app/controllers/bioschemas_controller.rb +++ b/app/controllers/bioschemas_controller.rb @@ -1,5 +1,5 @@ class BioschemasController < ApplicationController - before_action -> { feature_enabled?('bioschemas_testing') } + before_action -> { ensure_feature_enabled('bioschemas_testing') } def test diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb index 7809339e9..08831832b 100644 --- a/app/controllers/collections_controller.rb +++ b/app/controllers/collections_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Collection model class CollectionsController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_collection, only: %i[show edit curate update_curation add_item remove_item update destroy] before_action :set_breadcrumbs diff --git a/app/controllers/communities_controller.rb b/app/controllers/communities_controller.rb index db5182704..594a039ef 100644 --- a/app/controllers/communities_controller.rb +++ b/app/controllers/communities_controller.rb @@ -8,9 +8,9 @@ def show @resources = [] if TeSS::Config.solr_enabled enabled = [] - enabled.append(Event) if TeSS::Config.feature['events'] - enabled.append(Material) if TeSS::Config.feature['materials'] - enabled.append(Collection) if TeSS::Config.feature['collections'] + enabled.append(Event) if feature_enabled?('events') + enabled.append(Material) if feature_enabled?('materials') + enabled.append(Collection) if feature_enabled?('collections') enabled.each do |resource| @resources += resource.search_and_filter(nil, '', { 'max_age' => '1 month' }, sort_by: 'new', per_page: 5).results diff --git a/app/controllers/content_providers_controller.rb b/app/controllers/content_providers_controller.rb index 4897919bc..e287d7d76 100644 --- a/app/controllers/content_providers_controller.rb +++ b/app/controllers/content_providers_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Content Providers model class ContentProvidersController < ApplicationController - before_action -> { feature_enabled?('content_providers') } + before_action :ensure_feature_enabled before_action :set_content_provider, only: %i[show edit update destroy] before_action :set_breadcrumbs diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 413e78523..40df7990e 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -2,7 +2,7 @@ # The controller for actions related to the Events model class EventsController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_event, only: %i[show edit clone update destroy update_collections add_term reject_term redirect report update_report add_data reject_data] before_action :set_breadcrumbs diff --git a/app/controllers/learning_path_topics_controller.rb b/app/controllers/learning_path_topics_controller.rb index 7489e14fc..62c09fa5a 100644 --- a/app/controllers/learning_path_topics_controller.rb +++ b/app/controllers/learning_path_topics_controller.rb @@ -1,5 +1,5 @@ class LearningPathTopicsController < ApplicationController - before_action -> { feature_enabled?('learning_paths') } + before_action -> { ensure_feature_enabled('learning_paths') } before_action :set_topic, only: %i[show edit update destroy] before_action :set_breadcrumbs diff --git a/app/controllers/learning_paths_controller.rb b/app/controllers/learning_paths_controller.rb index a99105e8d..24d85d9f9 100644 --- a/app/controllers/learning_paths_controller.rb +++ b/app/controllers/learning_paths_controller.rb @@ -1,5 +1,5 @@ class LearningPathsController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_learning_path, only: [:show, :edit, :update, :destroy] before_action :set_breadcrumbs diff --git a/app/controllers/materials_controller.rb b/app/controllers/materials_controller.rb index 0322f4adc..72806976d 100644 --- a/app/controllers/materials_controller.rb +++ b/app/controllers/materials_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Materials model class MaterialsController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_material, only: %i[show edit update destroy update_collections clone add_term reject_term add_data reject_data] before_action :set_breadcrumbs @@ -17,7 +17,7 @@ class MaterialsController < ApplicationController # GET /materials.json?q=queryparam def index - elearning = @facet_params[:resource_type] == 'e-learning' && TeSS::Config.feature['elearning_materials'] + elearning = @facet_params[:resource_type] == 'e-learning' && feature_enabled?('elearning_materials') @bioschemas = @materials.flat_map(&:to_bioschemas) respond_to do |format| format.html { render elearning ? 'elearning_materials/index' : 'index' } diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb index 331a4a8dc..0821d470e 100644 --- a/app/controllers/nodes_controller.rb +++ b/app/controllers/nodes_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Nodes model class NodesController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_node, only: [:show, :edit, :update, :destroy] before_action :set_breadcrumbs diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 77e062876..a612ad898 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -54,11 +54,11 @@ def search_params def search_models return @_models if @_models @_models = ['User'] - @_models << 'Event' if TeSS::Config.feature['events'] - @_models << 'Material' if TeSS::Config.feature['materials'] - @_models << 'Collection' if TeSS::Config.feature['collections'] - @_models << 'ContentProvider' if TeSS::Config.feature['content_providers'] - @_models << 'Trainer' if TeSS::Config.feature['trainers'] + @_models << 'Event' if feature_enabled?('events') + @_models << 'Material' if feature_enabled?('materials') + @_models << 'Collection' if feature_enabled?('collections') + @_models << 'ContentProvider' if feature_enabled?('content_providers') + @_models << 'Trainer' if feature_enabled?('trainers') @_models end end diff --git a/app/controllers/spaces_controller.rb b/app/controllers/spaces_controller.rb index 8d118e303..9de4c6f3c 100644 --- a/app/controllers/spaces_controller.rb +++ b/app/controllers/spaces_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Spaces model class SpacesController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_space, only: [:show, :edit, :update, :destroy] before_action :set_breadcrumbs @@ -76,7 +76,7 @@ def set_space end def space_params - permitted = [:title, :description, :theme, :image, :image_url, { administrator_ids: [] }] + permitted = [:title, :description, :theme, :image, :image_url, { administrator_ids: [] }, { enabled_features: [] }] permitted += [:host] if current_user.is_admin? params.require(:space).permit(*permitted) end diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index bff25aa81..e5b3e5538 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -9,9 +9,9 @@ def home @resources = [] if TeSS::Config.solr_enabled enabled = [] - enabled.append(Event) if TeSS::Config.feature['events'] - enabled.append(Material) if TeSS::Config.feature['materials'] - enabled.append(Collection) if TeSS::Config.feature['collections'] + enabled.append(Event) if feature_enabled?('events') + enabled.append(Material) if feature_enabled?('materials') + enabled.append(Collection) if feature_enabled?('collections') enabled.each do |resource| @resources += resource.search_and_filter(nil, '', { 'max_age' => '1 month' }, sort_by: 'new', per_page: 5).results diff --git a/app/controllers/trainers_controller.rb b/app/controllers/trainers_controller.rb index 076086703..4fba487be 100644 --- a/app/controllers/trainers_controller.rb +++ b/app/controllers/trainers_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Profiles model class TrainersController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled before_action :set_trainer, only: [:show] before_action :set_breadcrumbs diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 36a2e73f9..6edf1ec50 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -2,7 +2,7 @@ # The controller for actions related to the Users model class UsersController < ApplicationController - before_action -> { feature_enabled?('invitation') }, only: [:invitees] + before_action -> { ensure_feature_enabled('invitation') }, only: [:invitees] prepend_before_action :set_user, only: %i[show edit update destroy change_token] prepend_before_action :init_user, only: [:create] before_action :set_breadcrumbs @@ -139,10 +139,6 @@ def user_params params.require(:user).permit(allowed_parameters) end - def invitees_enabled? - feature_enabled?('invitation') - end - # Prevent assigning other profiles def check_profile_id profile_id = @user.profile.id diff --git a/app/controllers/workflows_controller.rb b/app/controllers/workflows_controller.rb index 937f1bc2f..2af2055de 100644 --- a/app/controllers/workflows_controller.rb +++ b/app/controllers/workflows_controller.rb @@ -1,6 +1,6 @@ # The controller for actions related to the Workflows model class WorkflowsController < ApplicationController - before_action :feature_enabled? + before_action :ensure_feature_enabled layout 'application' diff --git a/app/helpers/spaces_helper.rb b/app/helpers/spaces_helper.rb index 276301526..9317ade62 100644 --- a/app/helpers/spaces_helper.rb +++ b/app/helpers/spaces_helper.rb @@ -3,4 +3,12 @@ module SpacesHelper def spaces_info I18n.t('info.spaces.description') end + + def space_feature_options + Space::FEATURES.select do |f| + TeSS::Config.feature[f] + end.map do |f| + [t("features.#{f}.short"), f] + end + end end diff --git a/app/models/default_space.rb b/app/models/default_space.rb index f0680d3d1..e29fd466a 100644 --- a/app/models/default_space.rb +++ b/app/models/default_space.rb @@ -60,4 +60,8 @@ def default? def administrators User.with_role('admin') end + + def feature_enabled?(feature) + TeSS::Config.feature[feature] + end end diff --git a/app/models/event.rb b/app/models/event.rb index 6f2cf0762..bc95db606 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -203,8 +203,8 @@ def self.facet_fields field_list.delete('sponsors') if TeSS::Config.feature['disabled'].include? 'sponsors' field_list.delete('tools') if TeSS::Config.feature['disabled'].include? 'biotools' field_list.delete('fields') if TeSS::Config.feature['disabled'].include? 'ardc_fields_of_research' - field_list.delete('node') unless TeSS::Config.feature['nodes'] - field_list.delete('collections') unless TeSS::Config.feature['collections'] + field_list.delete('node') unless Space.current_space.feature_enabled?('nodes') + field_list.delete('collections') unless Space.current_space.feature_enabled?('collections') field_list.delete('organizer') unless TeSS::Config.feature['organizer'] field_list.delete('contact') unless TeSS::Config.feature['contact'] diff --git a/app/models/learning_path.rb b/app/models/learning_path.rb index e2c380fa5..cafc70476 100644 --- a/app/models/learning_path.rb +++ b/app/models/learning_path.rb @@ -96,7 +96,7 @@ def self.facet_fields difficulty_level licence target_audience authors contributors user node status) field_list.delete('scientific_topics') if TeSS::Config.feature['disabled'].include? 'topics' - field_list.delete('node') unless TeSS::Config.feature['nodes'] + field_list.delete('node') unless Space.current_space.feature_enabled?('nodes') field_list.delete('status') if TeSS::Config.feature['disabled'].include? 'status' field_list diff --git a/app/models/material.rb b/app/models/material.rb index 9e1726c08..40e7fc83e 100644 --- a/app/models/material.rb +++ b/app/models/material.rb @@ -140,8 +140,8 @@ def self.facet_fields field_list.delete('standard_database_or_policy') if TeSS::Config.feature['disabled'].include? 'fairshare' field_list.delete('tools') if TeSS::Config.feature['disabled'].include? 'biotools' field_list.delete('fields') if TeSS::Config.feature['disabled'].include? 'ardc_fields_of_research' - field_list.delete('node') unless TeSS::Config.feature['nodes'] - field_list.delete('collections') unless TeSS::Config.feature['collections'] + field_list.delete('node') unless Space.current_space.feature_enabled?('nodes') + field_list.delete('collections') unless Space.current_space.feature_enabled?('collections') field_list.delete('status') if TeSS::Config.feature['disabled'].include? 'status' field_list diff --git a/app/models/source.rb b/app/models/source.rb index 889bf44a0..370b1d0da 100644 --- a/app/models/source.rb +++ b/app/models/source.rb @@ -74,7 +74,7 @@ def ingestor_class def self.facet_fields field_list = %w( content_provider node method enabled approval_status ) - field_list.delete('node') unless TeSS::Config.feature['nodes'] + field_list.delete('node') unless Space.current_space.feature_enabled?('nodes') field_list end diff --git a/app/models/space.rb b/app/models/space.rb index fc7049035..0398ac1d4 100644 --- a/app/models/space.rb +++ b/app/models/space.rb @@ -1,4 +1,6 @@ class Space < ApplicationRecord + FEATURES = %w[events materials elearning_materials learning_paths workflows collections trainers content_providers nodes].freeze + include PublicActivity::Common include LogParameterChanges @@ -15,6 +17,7 @@ class Space < ApplicationRecord has_many :administrators, through: :administrator_roles, source: :user, class_name: 'User' validates :theme, inclusion: { in: TeSS::Config.themes.keys, allow_blank: true } + validate :disabled_features_valid? has_image(placeholder: TeSS::Config.placeholder['content_provider']) @@ -45,4 +48,31 @@ def default? def users_with_role(role) space_role_users.joins(:space_roles).where(space_roles: { key: role }) end + + def feature_enabled?(feature) + if FEATURES.include?(feature) + TeSS::Config.feature[feature] && !disabled_features.include?(feature) + else + TeSS::Config.feature[feature] + end + end + + def enabled_features= features + self.disabled_features = (FEATURES - features) + end + + def enabled_features + (FEATURES - disabled_features) + end + + private + + def disabled_features_valid? + disabled_features.each do |feature| + next if feature.blank? + unless FEATURES.include?(feature) + errors.add(:disabled_features, :inclusion) + end + end + end end diff --git a/app/views/about/_about_nav.html.erb b/app/views/about/_about_nav.html.erb index 8350deb36..55efafdeb 100644 --- a/app/views/about/_about_nav.html.erb +++ b/app/views/about/_about_nav.html.erb @@ -24,7 +24,7 @@ - <% if TeSS::Config.feature['learning_paths'] %> + <% if feature_enabled?('learning_paths') %>