diff --git a/app/models/checklist.rb b/app/models/checklist.rb index 4150e1739..b5204f7b6 100644 --- a/app/models/checklist.rb +++ b/app/models/checklist.rb @@ -36,27 +36,19 @@ class Checklist < ApplicationRecord page = 1, _current_team = nil, options = {}) - step_ids = - Step - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) + step_ids = Step.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) - new_query = - Checklist - .distinct - .where('checklists.step_id IN (?)', step_ids) - .joins('LEFT JOIN checklist_items ON ' \ - 'checklists.id = checklist_items.checklist_id') - .where_attributes_like(['checklists.name', 'checklist_items.text'], - query, options) + new_query = Checklist.distinct + .where(checklists: { step_id: step_ids }) + .left_outer_joins(:checklist_items) + .where_attributes_like(['checklists.name', 'checklist_items.text'], query, options) # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end end diff --git a/app/models/comment.rb b/app/models/comment.rb index 70e3c68cd..6aad56787 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -18,46 +18,34 @@ class Comment < ApplicationRecord _current_team = nil, options = {} ) - project_ids = - Project - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) - my_module_ids = - MyModule - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) - step_ids = - Step - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) - result_ids = - Result - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) + project_ids = Project.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) + my_module_ids = MyModule.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) + step_ids = Step.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) + result_ids = Result.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) - new_query = - Comment.distinct - .joins(:user) - .where( - '(comments.associated_id IN (?) AND comments.type = ?) OR ' \ - '(comments.associated_id IN (?) AND comments.type = ?) OR ' \ - '(comments.associated_id IN (?) AND comments.type = ?) OR ' \ - '(comments.associated_id IN (?) AND comments.type = ?)', - project_ids, 'ProjectComment', - my_module_ids, 'TaskComment', - step_ids, 'StepComment', - result_ids, 'ResultComment' - ) - .where_attributes_like(['message', 'users.full_name'], - query, options) + new_query = Comment.distinct + .joins(:user) + .where( + '(comments.associated_id IN (?) AND comments.type = ?) OR ' \ + '(comments.associated_id IN (?) AND comments.type = ?) OR ' \ + '(comments.associated_id IN (?) AND comments.type = ?) OR ' \ + '(comments.associated_id IN (?) AND comments.type = ?)', + project_ids, 'ProjectComment', + my_module_ids, 'TaskComment', + step_ids, 'StepComment', + result_ids, 'ResultComment' + ) + .where_attributes_like(['message', 'users.full_name'], query, options) # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/concerns/permission_checkable_model.rb b/app/models/concerns/permission_checkable_model.rb index cb383f282..174748990 100644 --- a/app/models/concerns/permission_checkable_model.rb +++ b/app/models/concerns/permission_checkable_model.rb @@ -3,6 +3,16 @@ module PermissionCheckableModel extend ActiveSupport::Concern + included do + include PermissionExtends + + scope :with_granted_permissions, lambda { |user, permissions| + left_outer_joins(user_assignments: :user_role) + .where(user_assignments: { user: user }) + .where('user_roles.permissions @> ARRAY[?]::varchar[]', permissions) + } + end + def permission_granted?(user, permission) user_role_permissions = load_user_role_permissions(user) return false if user_role_permissions.blank? @@ -13,13 +23,10 @@ module PermissionCheckableModel private def load_user_role_permissions(user) - user_role_permissions = - if user_assignments.loaded? - user_assignments.detect { |user_assignment| user_assignment.user == user }&.user_role&.permissions - else - user_assignments.find_by(user: user)&.user_role&.permissions - end - - user_role_permissions + if user_assignments.loaded? + user_assignments.detect { |user_assignment| user_assignment.user == user }&.user_role&.permissions + else + user_assignments.find_by(user: user)&.user_role&.permissions + end end end diff --git a/app/models/experiment.rb b/app/models/experiment.rb index 8f93a6981..a1ce29bc5 100644 --- a/app/models/experiment.rb +++ b/app/models/experiment.rb @@ -69,47 +69,25 @@ class Experiment < ApplicationRecord current_team = nil, options = {} ) - experiment_scope = experiment_search_scope( - Project - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id), - user - ) + viewable_projects = Project.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT, current_team) + .pluck(:id) + new_query = Experiment.with_granted_permissions(user, ExperimentPermissions::READ) + .where(project: viewable_projects) + .where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - if current_team - new_query = experiment_search_scope( - Project.search( - user, - include_archived, - nil, - 1, - current_team - ).select('id'), - user - ).where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - return include_archived ? new_query : new_query.active - elsif include_archived - new_query = experiment_scope.where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - else - new_query = experiment_scope.active - .where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - end + new_query = new_query.active unless include_archived # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end def self.viewable_by_user(user, teams) - left_outer_joins(user_assignments: :user_role) + with_granted_permissions(user, ExperimentPermissions::READ) .where(project: Project.viewable_by_user(user, teams)) - .where(user_assignments: { user: user }) - .where('user_roles.permissions @> ARRAY[?]::varchar[]', %w[experiment_read]) end def archived_branch? diff --git a/app/models/my_module.rb b/app/models/my_module.rb index b2a8c8c91..ac45ca7a3 100644 --- a/app/models/my_module.rb +++ b/app/models/my_module.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class MyModule < ApplicationRecord - SEARCHABLE_ATTRIBUTES = %i(name description).freeze + SEARCHABLE_ATTRIBUTES = ['my_modules.name', 'my_modules.description'] include ArchivableModel include SearchableModel @@ -92,52 +92,26 @@ class MyModule < ApplicationRecord current_team = nil, options = {} ) - my_module_scope = my_module_search_scope( - Experiment - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id), - user - ) + viewable_experiments = Experiment.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT, current_team) + .pluck(:id) - if current_team - new_query = my_module_search_scope( - Experiment - .search(user, - include_archived, - nil, - 1, - current_team) - .select('id'), - user - ).where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) + new_query = MyModule.with_granted_permissions(user, MyModulePermissions::READ) + .where(experiment: viewable_experiments) + .where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - if include_archived - return new_query - else - return new_query.where('my_modules.archived = ?', false) - end - elsif include_archived - new_query = my_module_scope.where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - else - new_query = my_module_scope.where('my_modules.archived = ?', false) - .where_attributes_like(SEARCHABLE_ATTRIBUTES, query, options) - end + new_query = new_query.active unless include_archived # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end def self.viewable_by_user(user, teams) - left_outer_joins(user_assignments: :user_role) + with_granted_permissions(user, MyModulePermissions::READ) .where(experiment: Experiment.viewable_by_user(user, teams)) - .where(user_assignments: { user: user }) - .where('user_roles.permissions @> ARRAY[?]::varchar[]', %w[task_read]) end def navigable? diff --git a/app/models/project.rb b/app/models/project.rb index 1fc025760..deb8e9b1c 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -82,64 +82,15 @@ class Project < ApplicationRecord options = {} ) - if current_team - new_query = - Project - .distinct - .joins(:user_assignments) - .where('projects.team_id = ?', current_team.id) - unless user.user_teams.find_by(team: current_team).try(:admin?) - # Admins see all projects in the team - new_query = new_query.where( - 'projects.visibility = 1 OR user_assignments.user_id = ?', - user.id - ) - end - new_query = new_query.where_attributes_like('projects.name', query, options) - - if include_archived - return new_query - else - return new_query.where('projects.archived = ?', false) - end - else - new_query = Project - .distinct - .joins(team: :user_teams) - .where('user_teams.user_id = ?', user.id) - - if include_archived - new_query = - new_query - .joins(:user_assignments) - .where( - 'user_teams.role = 2 OR projects.visibility = 1 OR ' \ - 'user_assignments.user_id = ?', - user.id - ) - .where_attributes_like('projects.name', query, options) - - else - new_query = - new_query - .joins(:user_assignments) - .where( - 'user_teams.role = 2 OR projects.visibility = 1 OR ' \ - 'user_assignments.user_id = ?', - user.id - ) - .where_attributes_like('projects.name', query, options) - .where('projects.archived = ?', false) - end - end + new_query = Project.viewable_by_user(user, current_team || user.teams) + .where_attributes_like('projects.name', query, options) + new_query = new_query.active unless include_archived # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end @@ -147,15 +98,12 @@ class Project < ApplicationRecord # Admins see all projects in the team # Member of the projects can view # If project is visible everyone from the team can view it - Project.where(team: teams) - .left_outer_joins(team: :user_teams) - .left_outer_joins(user_assignments: :user_role) - .where('projects.visibility = 1 OR '\ - 'user_assignments.user_id = :user_id OR '\ - '(user_teams.user_id = :user_id AND user_teams.role = 2)', - user_id: user.id) - .where('user_roles.permissions @> ARRAY[?]::varchar[]', [ProjectPermissions::READ]) - .distinct + projects = Project.where(team: teams) + .left_outer_joins(team: :user_teams) + .left_outer_joins(user_assignments: :user_role) + projects.where('projects.visibility = 1 OR (user_teams.user_id = ? AND user_teams.role = 2)', user) + .or(projects.with_granted_permissions(user, ProjectPermissions::READ)) + .distinct end def permission_parent diff --git a/app/models/protocol.rb b/app/models/protocol.rb index dd0237e9f..3e7d4905e 100644 --- a/app/models/protocol.rb +++ b/app/models/protocol.rb @@ -123,14 +123,11 @@ class Protocol < ApplicationRecord _current_team = nil, options = {}) team_ids = Team.joins(:user_teams) - .where('user_teams.user_id = ?', user.id) + .where(user_teams: { user_id: user.id }) .distinct .pluck(:id) - module_ids = MyModule.search(user, - include_archived, - nil, - Constants::SEARCH_NO_LIMIT) + module_ids = MyModule.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) .pluck(:id) where_str = @@ -193,9 +190,7 @@ class Protocol < ApplicationRecord if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/report.rb b/app/models/report.rb index 573ed8bdc..6c412a481 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -65,24 +65,18 @@ class Report < ApplicationRecord options = {} ) - project_ids = - Project - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) + project_ids = Project.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) - new_query = - Report - .distinct - .where('reports.project_id IN (?)', project_ids) - .where_attributes_like(%i(name description), query, options) + new_query = Report.distinct + .where(reports: { project_id: project_ids }) + .where_attributes_like(%i(name description), query, options) # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 42fca0d88..42d1dd957 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -74,27 +74,17 @@ class Repository < RepositoryBase repository = nil, options = {} ) + serchable_row_fields = [RepositoryRow::PREFIXED_ID_SQL, 'repository_rows.name', 'users.full_name'] + repositories = repository&.id || Repository.accessible_by_teams(user.teams).pluck(:id) - readable_rows = RepositoryRow.joins(:repository).where(repository_id: repositories) + readable_rows = RepositoryRow.joins(:repository, :created_by).where(repository_id: repositories) - matched_by_user = readable_rows.joins(:created_by).where_attributes_like('users.full_name', query, options) - - prefixed_repository_row_ids = RepositoryRow.where(repository_id: repositories) - .where_attributes_like([RepositoryRow::PREFIXED_ID_SQL], query, options) - .select(:id) - - repository_row_matches = - readable_rows.where_attributes_like(['repository_rows.name'], query, options).or( - readable_rows.where('repository_rows.id' => prefixed_repository_row_ids) - ) - - repository_rows = readable_rows.where(id: repository_row_matches) - repository_rows = repository_rows.or(readable_rows.where(id: matched_by_user)) + repository_rows = readable_rows.where_attributes_like(serchable_row_fields, query, options) Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |_data_type, config| - custom_cell_matches = repository_rows.joins(config[:includes]) - .where_attributes_like(config[:field], query, options) + custom_cell_matches = readable_rows.joins(config[:includes]) + .where_attributes_like(config[:field], query, options) repository_rows = repository_rows.or(readable_rows.where(id: custom_cell_matches)) end @@ -103,8 +93,7 @@ class Repository < RepositoryBase repository_rows.select('repositories.id AS id, COUNT(DISTINCT repository_rows.id) AS counter') .group('repositories.id') else - repository_rows.limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + repository_rows.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/result.rb b/app/models/result.rb index f364ea4b8..495e33e70 100644 --- a/app/models/result.rb +++ b/app/models/result.rb @@ -32,28 +32,22 @@ class Result < ApplicationRecord page = 1, _current_team = nil, options = {}) - module_ids = - MyModule - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) + module_ids = MyModule.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT).pluck(:id) new_query = Result .distinct .joins('LEFT JOIN result_texts ON results.id = result_texts.result_id') - .where('results.my_module_id IN (?)', module_ids) - .where_attributes_like(['results.name', 'result_texts.text'], - query, options) + .where(results: { my_module_id: module_ids }) + .where_attributes_like(['results.name', 'result_texts.text'], query, options) - new_query = new_query.where('results.archived = ?', false) unless include_archived + new_query = new_query.active unless include_archived # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/step.rb b/app/models/step.rb index 940f52ecc..2da8c1184 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -51,23 +51,18 @@ class Step < ApplicationRecord page = 1, _current_team = nil, options = {}) - protocol_ids = - Protocol - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) + protocol_ids = Protocol.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) - new_query = Step - .distinct - .where('steps.protocol_id IN (?)', protocol_ids) - .where_attributes_like([:name, :description], query, options) + new_query = Step.distinct + .where(steps: { protocol_id: protocol_ids }) + .where_attributes_like(%i(name description), query, options) # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/table.rb b/app/models/table.rb index a4b37df71..130971ea5 100644 --- a/app/models/table.rb +++ b/app/models/table.rb @@ -35,29 +35,19 @@ class Table < ApplicationRecord page = 1, _current_team = nil, options = {}) - step_ids = - Step - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .joins(:step_tables) - .distinct - .pluck('step_tables.id') + step_ids = Step.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .joins(:step_tables) + .distinct + .pluck('step_tables.id') - result_ids = - Result - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .joins(:result_table) - .distinct - .pluck('result_tables.id') + result_ids = Result.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .joins(:result_table) + .distinct + .pluck('result_tables.id') - table_query = - Table - .distinct - .joins('LEFT OUTER JOIN step_tables ON step_tables.table_id = tables.id') - .joins('LEFT OUTER JOIN result_tables ON ' \ - 'result_tables.table_id = tables.id') - .joins('LEFT OUTER JOIN results ON result_tables.result_id = results.id') - .where('step_tables.id IN (?) OR result_tables.id IN (?)', - step_ids, result_ids) + table_query = Table.distinct + .left_outer_joins(:step_table, :result_table, :result) + .where('step_tables.id IN (?) OR result_tables.id IN (?)', step_ids, result_ids) if options[:whole_word].to_s == 'true' || options[:whole_phrase].to_s == 'true' @@ -111,9 +101,7 @@ class Table < ApplicationRecord if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end diff --git a/app/models/tag.rb b/app/models/tag.rb index 9ef34bc72..85f46ca60 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -24,23 +24,19 @@ class Tag < ApplicationRecord page = 1, _current_team = nil, options = {}) - project_ids = - Project - .search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) - .pluck(:id) + project_ids = Project.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT) + .pluck(:id) new_query = Tag .distinct - .where('tags.project_id IN (?)', project_ids) + .where(tags: { project_id: project_ids }) .where_attributes_like(:name, query, options) # Show all results if needed if page == Constants::SEARCH_NO_LIMIT new_query else - new_query - .limit(Constants::SEARCH_LIMIT) - .offset((page - 1) * Constants::SEARCH_LIMIT) + new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end end diff --git a/app/models/user.rb b/app/models/user.rb index 43b7460ea..2b135122d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -369,24 +369,14 @@ class User < ApplicationRecord team_to_ignore = nil ) result = User.all - - if active_only - result = result.where.not(confirmed_at: nil) - end + result = result.where.not(confirmed_at: nil) if active_only if team_to_ignore.present? - ignored_ids = - UserTeam - .select(:user_id) - .where(team_id: team_to_ignore.id) - result = - result - .where("users.id NOT IN (?)", ignored_ids) + ignored_ids = UserTeam.select(:user_id).where(team_id: team_to_ignore.id) + result = result.where.not(users: { id: ignored_ids }) end - result - .where_attributes_like([:full_name, :email], query) - .distinct + result.where_attributes_like(%i(full_name email), query).distinct end # Whether user is active (= confirmed) or not diff --git a/config/initializers/extends/permission_extends.rb b/config/initializers/extends/permission_extends.rb index fa2e15ad3..9e935ca68 100644 --- a/config/initializers/extends/permission_extends.rb +++ b/config/initializers/extends/permission_extends.rb @@ -22,12 +22,10 @@ module PermissionExtends %w( READ READ_ARCHIVED - ACTIVITIES_READ MANAGE TASKS_MANAGE USERS_READ USERS_MANAGE - READ_ARCHIVED READ_CANVAS ACTIVITIES_READ ).each { |permission| const_set(permission, "experiment_#{permission.underscore}") }