From f68d724202a87274437817f6242e6f40ba3881bc Mon Sep 17 00:00:00 2001 From: artoscinote <85488244+artoscinote@users.noreply.github.com> Date: Thu, 30 Sep 2021 11:32:11 +0200 Subject: [PATCH] Rework experiment permissions [SCI-6054] (#3538) * Rework experiment permissions [SCI-6054] --- Gemfile | 1 + Gemfile.lock | 6 ++ .../experiments_controller.rb | 2 +- app/controllers/api/v1/tasks_controller.rb | 2 +- app/controllers/experiments_controller.rb | 29 ++++--- app/controllers/my_modules_controller.rb | 6 +- .../project_comments_controller.rb | 6 +- app/controllers/result_comments_controller.rb | 2 +- app/controllers/step_comments_controller.rb | 15 +++- app/helpers/comment_helper.rb | 4 +- .../generate_user_assignments_job.rb | 5 +- app/models/concerns/assignable.rb | 10 ++- app/models/experiment.rb | 13 ++- app/models/my_module.rb | 10 ++- app/models/project.rb | 4 +- app/models/user.rb | 4 +- app/models/user_role.rb | 84 ++---------------- app/permissions/experiment.rb | 47 +++++----- app/permissions/my_module.rb | 48 +++++++---- app/permissions/project.rb | 18 +++- app/permissions/result.rb | 6 +- .../experiments/move_to_project_service.rb | 7 +- app/services/experiments_overview_service.rb | 3 +- app/services/report_actions/report_content.rb | 2 +- app/services/templates_service.rb | 3 +- .../_experiment_actions_dropdown.html.erb | 2 +- .../results/partials/_asset_text.html.erb | 2 +- .../shared/sidebar/_experiments.html.erb | 2 +- .../extends/permission_extends.rb | 85 +++++++++++++++++++ features/support/env.rb | 25 ++++++ .../experiments_controller_spec.rb | 4 +- .../my_modules_controller_spec.rb | 6 +- .../projects_controller_spec.rb | 2 +- spec/controllers/assets_controller_spec.rb | 2 +- spec/controllers/canvas_controller_spec.rb | 16 ++-- .../my_module_comments_controller_spec.rb | 2 +- .../my_module_repositories_controller_spec.rb | 8 +- .../controllers/my_modules_controller_spec.rb | 10 +-- spec/controllers/reports_controller_spec.rb | 2 +- spec/controllers/teams_controller_spec.rb | 1 - spec/factories/experiments.rb | 2 +- spec/factories/my_modules.rb | 4 + spec/factories/user_roles.rb | 38 +-------- .../activities/dispatch_webhooks_job_spec.rb | 2 +- spec/jobs/activities/send_webhook_job_spec.rb | 4 +- .../generate_user_assignments_job_spec.rb | 23 +++-- .../propagate_assignment_job_spec.rb | 8 +- spec/lib/tasks/my_modules_spec.rb | 2 +- spec/models/experiment_member_spec.rb | 3 +- spec/models/my_module_member_spec.rb | 5 +- spec/models/project_member_spec.rb | 13 +-- spec/models/project_spec.rb | 2 +- .../controllers/canvas_controller_spec.rb | 2 +- spec/permissions/result_permission_spec.rb | 5 +- spec/rails_helper.rb | 41 ++++++++- .../requests/api/v1/assets_controller_spec.rb | 2 +- .../api/v1/checklist_items_controller_spec.rb | 2 +- .../api/v1/checklists_controller_spec.rb | 2 +- ...riment_user_assignments_controller_spec.rb | 2 +- .../api/v1/experiments_controller_spec.rb | 2 +- ...roject_user_assignments_controller_spec.rb | 2 +- .../api/v1/projects_controller_spec.rb | 2 +- .../api/v1/results_controller_spec.rb | 2 +- spec/requests/api/v1/steps_controller_spec.rb | 2 +- .../requests/api/v1/tables_controller_spec.rb | 2 +- .../task_user_assignments_controller_spec.rb | 4 +- spec/requests/api/v1/tasks_controller_spec.rb | 2 +- .../move_to_project_service_spec.rb | 9 +- .../experiments_overview_service_spec.rb | 2 +- .../smart_annotations/html_preview_spec.rb | 2 +- .../smart_annotations/permission_eval_spec.rb | 4 +- .../smart_annotations/tag_to_html_spec.rb | 2 +- .../smart_annotations/tag_to_text_spec.rb | 2 +- .../smart_annotations/text_preview_spec.rb | 2 +- .../reference_project_structure_context.rb | 16 ++-- ...troller_action_with_permission_checking.rb | 2 +- 76 files changed, 421 insertions(+), 306 deletions(-) diff --git a/Gemfile b/Gemfile index f36c26e60..6c98af75b 100644 --- a/Gemfile +++ b/Gemfile @@ -134,6 +134,7 @@ group :test do gem 'capybara' gem 'capybara-email' gem 'cucumber-rails', '~> 1.8', require: false + gem 'database_cleaner' gem 'json_matchers' gem 'selenium-webdriver' gem 'shoulda-matchers' diff --git a/Gemfile.lock b/Gemfile.lock index 69c3ef9c5..eb4f88504 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -236,6 +236,12 @@ GEM railties (>= 4.2, < 7) cucumber-tag_expressions (1.1.1) cucumber-wire (0.0.1) + 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) debug_inspector (1.0.0) deface (1.6.1) nokogiri (>= 1.6) diff --git a/app/controllers/access_permissions/experiments_controller.rb b/app/controllers/access_permissions/experiments_controller.rb index 2f9daa937..fb8af1948 100644 --- a/app/controllers/access_permissions/experiments_controller.rb +++ b/app/controllers/access_permissions/experiments_controller.rb @@ -50,7 +50,7 @@ module AccessPermissions end def check_manage_permissions - render_403 unless can_manage_experiment_access?(@experiment) + render_403 unless can_manage_experiment_users?(@experiment) end def check_read_permissions diff --git a/app/controllers/api/v1/tasks_controller.rb b/app/controllers/api/v1/tasks_controller.rb index d29179ac4..26a26f621 100644 --- a/app/controllers/api/v1/tasks_controller.rb +++ b/app/controllers/api/v1/tasks_controller.rb @@ -36,7 +36,7 @@ module Api def create raise PermissionError.new(MyModule, :create) unless can_manage_experiment?(@experiment) - my_module = @experiment.my_modules.create!(task_params_create) + my_module = @experiment.my_modules.create!(task_params_create.merge(created_by: current_user)) render jsonapi: my_module, serializer: TaskSerializer, rte_rendering: render_rte?, diff --git a/app/controllers/experiments_controller.rb b/app/controllers/experiments_controller.rb index a937836cf..e99b7a07b 100644 --- a/app/controllers/experiments_controller.rb +++ b/app/controllers/experiments_controller.rb @@ -9,9 +9,11 @@ class ExperimentsController < ApplicationController before_action :load_project, only: %i(new create archive_group restore_group) before_action :load_experiment, except: %i(new create archive_group restore_group) - before_action :check_view_permissions, except: %i(edit archive clone move new create archive_group restore_group) + before_action :check_read_permissions, except: %i(edit archive clone move new create archive_group restore_group) + before_action :check_canvas_read_permissions, only: %i(canvas) before_action :check_create_permissions, only: %i(new create) before_action :check_manage_permissions, only: %i(edit) + before_action :check_update_permissions, only: %i(update) before_action :check_archive_permissions, only: :archive before_action :check_clone_permissions, only: %i(clone_modal clone) before_action :check_move_permissions, only: %i(move_modal move) @@ -82,12 +84,6 @@ class ExperimentsController < ApplicationController end def update - render_403 && return unless if experiment_params[:archived] == 'false' - can_restore_experiment?(@experiment) - else - can_manage_experiment?(@experiment) - end - old_text = @experiment.description @experiment.assign_attributes(experiment_params) @experiment.last_modified_by = current_user @@ -221,7 +217,7 @@ class ExperimentsController < ApplicationController # GET: move_modal_experiment_path(id) def move_modal - @projects = @experiment.moveable_projects(current_user) + @projects = @experiment.movable_projects(current_user) respond_to do |format| format.json do render json: { @@ -309,8 +305,13 @@ class ExperimentsController < ApplicationController params.require(:experiment).require(:project_id) end - def check_view_permissions - render_403 unless can_read_experiment?(@experiment) + def check_read_permissions + render_403 unless can_read_experiment?(@experiment) || + @experiment.archived? && can_read_archived_experiment?(@experiment) + end + + def check_canvas_read_permissions + render 403 unless can_read_experiment_canvas?(@experiment) end def check_create_permissions @@ -321,6 +322,14 @@ class ExperimentsController < ApplicationController render_403 unless can_manage_experiment?(@experiment) end + def check_update_permissions + if experiment_params[:archived] == 'false' + render_403 unless can_restore_experiment?(@experiment) + else + render_403 unless can_manage_experiment?(@experiment) + end + end + def check_archive_permissions render_403 unless can_archive_experiment?(@experiment) end diff --git a/app/controllers/my_modules_controller.rb b/app/controllers/my_modules_controller.rb index 97df0194c..85f0577a4 100644 --- a/app/controllers/my_modules_controller.rb +++ b/app/controllers/my_modules_controller.rb @@ -9,7 +9,7 @@ class MyModulesController < ApplicationController before_action :load_vars, except: %i(restore_group) before_action :check_archive_permissions, only: %i(update) before_action :check_manage_permissions, only: %i(description due_date update_description update_protocol_description) - before_action :check_view_permissions, except: %i(update update_description update_protocol_description restore_group) + before_action :check_read_permissions, except: %i(update update_description update_protocol_description restore_group) before_action :check_update_state_permissions, only: :update_state before_action :set_inline_name_editing, only: %i(protocols results activities archive) before_action :load_experiment_my_modules, only: %i(protocols results activities archive) @@ -327,8 +327,8 @@ class MyModulesController < ApplicationController return render_403 if my_module_params[:archived] == 'true' && !can_archive_my_module?(@my_module) end - def check_view_permissions - render_403 unless can_read_protocol_in_module?(@my_module.protocol) + def check_read_permissions + render_403 unless can_read_my_module?(@my_module) end def check_update_state_permissions diff --git a/app/controllers/project_comments_controller.rb b/app/controllers/project_comments_controller.rb index 7be3f3b77..4de02cdea 100644 --- a/app/controllers/project_comments_controller.rb +++ b/app/controllers/project_comments_controller.rb @@ -41,7 +41,7 @@ class ProjectCommentsController < ApplicationController def load_vars @last_comment_id = params[:from].to_i @per_page = Constants::COMMENTS_SEARCH_LIMIT - @project = Project.find_by_id(params[:project_id]) + @project = current_team.projects.find_by(id: params[:project_id]) render_404 unless @project end @@ -55,9 +55,9 @@ class ProjectCommentsController < ApplicationController end def check_manage_permissions - @comment = ProjectComment.find_by_id(params[:id]) + @comment = @project.project_comments.find_by(id: params[:id]) render_403 unless @comment.present? && - can_manage_project_comments?(@project) + can_manage_project_comment?(@comment) end def comment_params diff --git a/app/controllers/result_comments_controller.rb b/app/controllers/result_comments_controller.rb index e0d81d10f..a4ca7b14c 100644 --- a/app/controllers/result_comments_controller.rb +++ b/app/controllers/result_comments_controller.rb @@ -57,7 +57,7 @@ class ResultCommentsController < ApplicationController end def check_manage_permissions - @comment = ResultComment.find_by_id(params[:id]) + @comment = @result.result_comments.find_by(id: params[:id]) render_403 unless @comment.present? && can_manage_result_comment?(@comment) end diff --git a/app/controllers/step_comments_controller.rb b/app/controllers/step_comments_controller.rb index 405dd141e..fbecb8e16 100644 --- a/app/controllers/step_comments_controller.rb +++ b/app/controllers/step_comments_controller.rb @@ -10,7 +10,8 @@ class StepCommentsController < ApplicationController before_action :check_view_permissions, only: [:index] before_action :check_add_permissions, only: [:create] - before_action :check_manage_permissions, only: %i(update destroy) + before_action :check_update_permissions, only: %i(update) + before_action :check_destroy_permissions, only: %i(destroy) def index comments = @step.last_comments(@last_comment_id, @per_page) @@ -56,10 +57,16 @@ class StepCommentsController < ApplicationController render_403 unless can_create_my_module_comments?(@protocol.my_module) end - def check_manage_permissions - @comment = StepComment.find_by_id(params[:id]) + def check_destroy_permissions + @comment = @step.step_comments.find_by(id: params[:id]) render_403 unless @comment.present? && - can_manage_comment_in_module?(@comment.becomes(Comment)) + can_delete_comment_in_my_module_steps?(@comment) + end + + def check_update_permissions + @comment = @step.step_comments.find_by(id: params[:id]) + render_403 unless @comment.present? && + can_update_comment_in_my_module_steps?(@comment) end def comment_params diff --git a/app/helpers/comment_helper.rb b/app/helpers/comment_helper.rb index 0dd6f23fc..ad562acad 100644 --- a/app/helpers/comment_helper.rb +++ b/app/helpers/comment_helper.rb @@ -76,11 +76,11 @@ module CommentHelper when 'TaskComment' can_manage_my_module_comment?(comment) when 'StepComment' - can_manage_comment_in_module?(comment.becomes(Comment)) + can_manage_my_module_step_comment?(comment) when 'ResultComment' can_manage_result_comment?(comment.becomes(Comment)) when 'ProjectComment' - can_manage_comment_in_project?(comment) + can_manage_project_comment?(comment) else false end diff --git a/app/jobs/user_assignments/generate_user_assignments_job.rb b/app/jobs/user_assignments/generate_user_assignments_job.rb index 249426d5b..37c4b72ca 100644 --- a/app/jobs/user_assignments/generate_user_assignments_job.rb +++ b/app/jobs/user_assignments/generate_user_assignments_job.rb @@ -7,9 +7,10 @@ module UserAssignments def perform(object, assigned_by) @assigned_by = assigned_by ActiveRecord::Base.transaction do - if object.is_a? Experiment + case object + when Experiment assign_users_to_experiment(object) - elsif object.is_a? MyModule + when MyModule assign_users_to_my_module(object) end end diff --git a/app/models/concerns/assignable.rb b/app/models/concerns/assignable.rb index c51665693..24f3b2589 100644 --- a/app/models/concerns/assignable.rb +++ b/app/models/concerns/assignable.rb @@ -4,12 +4,20 @@ module Assignable extend ActiveSupport::Concern included do + include Canaid::Helpers::PermissionsHelper + has_many :user_assignments, as: :assignable, dependent: :destroy default_scope { includes(user_assignments: :user_role) } + scope :readable_by_user, lambda { |user| + joins(user_assignments: :user_role) + .where(user_assignments: { user: user }) + .where('? = ANY(user_roles.permissions)', "::#{self.class.to_s.split('::').first}Permissions".constantize::READ) + } + after_create_commit do - UserAssignment.create( + UserAssignment.create!( user: created_by, assignable: self, user_role: UserRole.find_by(name: I18n.t('user_roles.predefined.owner')) diff --git a/app/models/experiment.rb b/app/models/experiment.rb index e28dc726d..0c27fdd70 100644 --- a/app/models/experiment.rb +++ b/app/models/experiment.rb @@ -237,14 +237,11 @@ class Experiment < ApplicationRecord # Projects to which this experiment can be moved (inside the same # team and not archived), all users assigned on experiment.project has # to be assigned on such project - def moveable_projects(current_user) - projects = projects_with_role_above_user(current_user) - - projects = projects.each_with_object([]) do |p, arr| - arr << p if (project.users - p.users).empty? - arr + def movable_projects(current_user) + current_user.projects.where.not(id: project_id).where(archived: false, team: project.team).select do |p| + can_create_project_experiments?(current_user, p) && + project.users == p.users end - projects - [project] end def permission_parent @@ -274,7 +271,7 @@ class Experiment < ApplicationRecord cloned_pairs = {} ids_map = {} to_add.each do |m| - original = MyModule.find_by_id(to_clone.fetch(m[:id], nil)) if to_clone.present? + original = MyModule.find_by(id: to_clone.fetch(m[:id], nil)) if to_clone.present? if original.present? my_module = original.deep_clone(current_user) cloned_pairs[my_module] = original diff --git a/app/models/my_module.rb b/app/models/my_module.rb index e8863e77f..acbf1f131 100644 --- a/app/models/my_module.rb +++ b/app/models/my_module.rb @@ -364,7 +364,15 @@ class MyModule < ApplicationRecord def deep_clone_to_experiment(current_user, experiment_dest) # Copy the module - clone = MyModule.new(name: name, experiment: experiment_dest, description: description, x: x, y: y) + clone = MyModule.new( + name: name, + experiment: experiment_dest, + description: description, + x: x, + y: y, + created_by: created_by + ) + # set new position if cloning in the same experiment clone.attributes = get_new_position if clone.experiment == experiment diff --git a/app/models/project.rb b/app/models/project.rb index 3bc1788eb..171cd9e32 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -209,7 +209,7 @@ class Project < ApplicationRecord user_assignments.find_by_user_id(user)&.user_role.name end - def sorted_experiments(sort_by = :new, archived = false) + def sorted_experiments(user, sort_by = :new, archived = false) sort = case sort_by when 'old' then { created_at: :asc } when 'atoz' then { name: :asc } @@ -218,7 +218,7 @@ class Project < ApplicationRecord when 'archived_old' then { archived_on: :asc } else { created_at: :desc } end - experiments.is_archived(archived).order(sort) + experiments.readable_by_user(user).is_archived(archived).order(sort) end def archived_experiments diff --git a/app/models/user.rb b/app/models/user.rb index d761e8eb0..43b7460ea 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -63,9 +63,9 @@ class User < ApplicationRecord has_many :teams, through: :user_teams has_many :user_assignments, dependent: :destroy has_many :user_projects, inverse_of: :user - has_many :projects, through: :user_projects + has_many :projects, through: :user_assignments, source: :assignable, source_type: 'Project' has_many :user_my_modules, inverse_of: :user - has_many :my_modules, through: :user_my_modules + has_many :my_modules, through: :user_assignments, source: :assignable, source_type: 'MyModule' has_many :comments, inverse_of: :user has_many :activities, inverse_of: :owner, foreign_key: 'owner_id' has_many :results, inverse_of: :user diff --git a/app/models/user_role.rb b/app/models/user_role.rb index bd71722f0..6361f523a 100644 --- a/app/models/user_role.rb +++ b/app/models/user_role.rb @@ -11,16 +11,14 @@ class UserRole < ApplicationRecord validates :created_by, presence: true, unless: :predefined? validates :last_modified_by, presence: true, unless: :predefined? - belongs_to :created_by, foreign_key: 'created_by_id', class_name: 'User', optional: true - belongs_to :last_modified_by, foreign_key: 'last_modified_by_id', class_name: 'User', optional: true + belongs_to :created_by, class_name: 'User', optional: true + belongs_to :last_modified_by, class_name: 'User', optional: true has_many :user_assignments, dependent: :destroy def self.owner_role new( name: I18n.t('user_roles.predefined.owner'), - permissions: ProjectPermissions.constants.map { |const| ProjectPermissions.const_get(const) } + - ExperimentPermissions.constants.map { |const| ExperimentPermissions.const_get(const) } + - MyModulePermissions.constants.map { |const| MyModulePermissions.const_get(const) }, + permissions: PredefinedRoles::OWNER_PERMISSIONS, predefined: true ) end @@ -28,39 +26,7 @@ class UserRole < ApplicationRecord def self.normal_user_role new( name: I18n.t('user_roles.predefined.normal_user'), - permissions: - [ - ProjectPermissions::READ, - ProjectPermissions::READ_ARCHIVED, - ProjectPermissions::ACTIVITIES_READ, - ProjectPermissions::USERS_READ, - ProjectPermissions::COMMENTS_READ, - ProjectPermissions::COMMENTS_CREATE, - ProjectPermissions::EXPERIMENTS_CREATE, - ExperimentPermissions::READ, - ExperimentPermissions::MANAGE, - ExperimentPermissions::TASKS_MANAGE, - MyModulePermissions::READ, - MyModulePermissions::MANAGE, - MyModulePermissions::RESULTS_MANAGE, - MyModulePermissions::PROTOCOL_MANAGE, - MyModulePermissions::STEPS_MANAGE, - MyModulePermissions::TAGS_MANAGE, - MyModulePermissions::COMMENTS_CREATE, - MyModulePermissions::COMMENTS_MANAGE, - MyModulePermissions::COMMENTS_MANAGE_OWN, - MyModulePermissions::COMPLETE, - MyModulePermissions::UPDATE_STATUS, - MyModulePermissions::STEPS_COMPLETE, - MyModulePermissions::STEPS_UNCOMPLETE, - MyModulePermissions::STEPS_CHECKLIST_CHECK, - MyModulePermissions::STEPS_CHECKLIST_UNCHECK, - MyModulePermissions::STEPS_COMMENTS_CREATE, - MyModulePermissions::STEPS_COMMENTS_DELETE_OWN, - MyModulePermissions::STEPS_COMMENT_UPDATE_OWN, - MyModulePermissions::REPOSITORY_ROWS_ASSIGN, - MyModulePermissions::REPOSITORY_ROWS_MANAGE - ], + permissions: PredefinedRoles::NORMAL_USER_PERMISSIONS, predefined: true ) end @@ -68,33 +34,7 @@ class UserRole < ApplicationRecord def self.technician_role new( name: I18n.t('user_roles.predefined.technician'), - permissions: - [ - ProjectPermissions::READ, - ProjectPermissions::READ_ARCHIVED, - ProjectPermissions::ACTIVITIES_READ, - ProjectPermissions::USERS_READ, - ProjectPermissions::COMMENTS_READ, - ProjectPermissions::COMMENTS_CREATE, - ExperimentPermissions::READ, - ExperimentPermissions::READ_ARCHIVED, - ExperimentPermissions::ACTIVITIES_READ, - ExperimentPermissions::USERS_READ, - MyModulePermissions::READ, - MyModulePermissions::COMMENTS_CREATE, - MyModulePermissions::COMMENTS_MANAGE_OWN, - MyModulePermissions::COMPLETE, - MyModulePermissions::UPDATE_STATUS, - MyModulePermissions::STEPS_COMPLETE, - MyModulePermissions::STEPS_UNCOMPLETE, - MyModulePermissions::STEPS_CHECKLIST_CHECK, - MyModulePermissions::STEPS_CHECKLIST_UNCHECK, - MyModulePermissions::STEPS_COMMENTS_CREATE, - MyModulePermissions::STEPS_COMMENTS_DELETE_OWN, - MyModulePermissions::STEPS_COMMENT_UPDATE_OWN, - MyModulePermissions::REPOSITORY_ROWS_ASSIGN, - MyModulePermissions::REPOSITORY_ROWS_MANAGE - ], + permissions: PredefinedRoles::TECHNICIAN_PERMISSIONS, predefined: true ) end @@ -102,19 +42,7 @@ class UserRole < ApplicationRecord def self.viewer_role new( name: I18n.t('user_roles.predefined.viewer'), - permissions: - [ - ProjectPermissions::READ, - ProjectPermissions::READ_ARCHIVED, - ProjectPermissions::ACTIVITIES_READ, - ProjectPermissions::USERS_READ, - ProjectPermissions::COMMENTS_READ, - ExperimentPermissions::READ, - ExperimentPermissions::READ_ARCHIVED, - ExperimentPermissions::ACTIVITIES_READ, - ExperimentPermissions::USERS_READ, - MyModulePermissions::READ - ], + permissions: PredefinedRoles::VIEWER_PERMISSIONS, predefined: true ) end diff --git a/app/permissions/experiment.rb b/app/permissions/experiment.rb index 81dd5c1df..091af9aee 100644 --- a/app/permissions/experiment.rb +++ b/app/permissions/experiment.rb @@ -1,6 +1,8 @@ Canaid::Permissions.register_for(Experiment) do # Experiment and its project must be active for all the specified permissions %i(manage_experiment + manage_experiment_tasks + manage_experiment_users archive_experiment clone_experiment move_experiment @@ -12,18 +14,6 @@ Canaid::Permissions.register_for(Experiment) do end end - # experiment: read (read archive) - # canvas: read - # module: read (read users, read comments, read archive) - # result: read (read comments) - can :read_experiment do |user, experiment| - experiment.permission_granted?(user, ExperimentPermissions::READ) - end - - can :read_users_of_experiment do |user, project| - project.permission_granted?(user, ExperimentPermissions::USERS_READ) - end - # experiment: create/update/delete # canvas: update # module: create, copy, reposition, create/update/delete connection, @@ -42,19 +32,38 @@ Canaid::Permissions.register_for(Experiment) do end end - # experiment: manage access policies - can :manage_experiment_access do |user, experiment| + can :read_experiment do |user, experiment| + experiment.permission_granted?(user, ExperimentPermissions::READ) + end + + can :read_archived_experiment do |user, experiment| + experiment.permission_granted?(user, ExperimentPermissions::READ_ARCHIVED) + end + + can :read_experiment_canvas do |user, experiment| + experiment.permission_granted?(user, ExperimentPermissions::READ_CANVAS) + end + + can :read_experiment_activities do |user, experiment| + experiment.permission_granted?(user, ExperimentPermissions::ACTIVITIES_READ) + end + + can :read_experiment_users do |user, experiment| + experiment.permission_granted?(user, ExperimentPermissions::USERS_READ) + end + + can :manage_experiment_users do |user, experiment| experiment.permission_granted?(user, ExperimentPermissions::USERS_MANAGE) end - # experiment: archive + can :manage_experiment_tasks do |user, experiment| + experiment.permission_granted?(user, ExperimentPermissions::TASKS_MANAGE) + end + can :archive_experiment do |user, experiment| experiment.permission_granted?(user, ExperimentPermissions::MANAGE) end - # NOTE: Must not be dependent on canaid parmision for which we check if it's - # active - # experiment: restore can :restore_experiment do |user, experiment| project = experiment.project experiment.permission_granted?(user, ExperimentPermissions::MANAGE) && @@ -62,12 +71,10 @@ Canaid::Permissions.register_for(Experiment) do project.active? end - # experiment: copy can :clone_experiment do |user, experiment| experiment.permission_granted?(user, ExperimentPermissions::MANAGE) end - # experiment: move can :move_experiment do |user, experiment| experiment.permission_granted?(user, ExperimentPermissions::MANAGE) end diff --git a/app/permissions/my_module.rb b/app/permissions/my_module.rb index 06f0da0c8..9931b8032 100644 --- a/app/permissions/my_module.rb +++ b/app/permissions/my_module.rb @@ -107,22 +107,6 @@ Canaid::Permissions.register_for(MyModule) do my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_CREATE) end - can :delete_comments_in_my_module_steps do |user, my_module| - my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_DELETE) - end - - can :delete_own_comments_in_my_module_steps do |user, my_module| - my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_DELETE_OWN) - end - - can :update_comments_in_my_module_steps do |user, my_module| - my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_UPDATE) - end - - can :update_own_comments_in_my_module_steps do |user, my_module| - my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENT_UPDATE_OWN) - end - can :manage_my_module_users do |user, my_module| my_module.permission_granted?(user, MyModulePermissions::MANAGE) end @@ -146,7 +130,7 @@ Canaid::Permissions.register_for(TaskComment) do %i(manage_my_module_comment) .each do |perm| can perm do |_, comment| - my_module = ::PermissionsUtil.get_comment_module(comment) + my_module = comment.my_module my_module.active? && my_module.experiment.active? && my_module.experiment.project.active? @@ -154,8 +138,36 @@ Canaid::Permissions.register_for(TaskComment) do end can :manage_my_module_comment do |user, comment| - my_module = ::PermissionsUtil.get_comment_module(comment) + my_module = comment.my_module my_module.permission_granted?(user, MyModulePermissions::COMMENTS_MANAGE) || ((comment.user == user) && my_module.permission_granted?(user, MyModulePermissions::COMMENTS_MANAGE_OWN)) end end + +Canaid::Permissions.register_for(StepComment) do + # Module, its experiment and its project must be active for all the specified + # permissions + %i(delete_comment_in_my_module_steps + update_comment_in_my_module_steps) + .each do |perm| + can perm do |_, comment| + my_module = comment.step.my_module + my_module.active? && + !my_module.archived_branch? && + my_module.experiment.active? && + my_module.experiment.project.active? + end + end + + can :delete_comment_in_my_module_steps do |user, comment| + my_module = comment.step.my_module + my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_DELETE) || + ((comment.user == user) && my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_DELETE_OWN)) + end + + can :update_comment_in_my_module_steps do |user, comment| + my_module = comment.step.my_module + my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_UPDATE) || + ((comment.user == user) && my_module.permission_granted?(user, MyModulePermissions::STEPS_COMMENTS_UPDATE_OWN)) + end +end diff --git a/app/permissions/project.rb b/app/permissions/project.rb index 9ec1cda28..29c705a0e 100644 --- a/app/permissions/project.rb +++ b/app/permissions/project.rb @@ -38,6 +38,14 @@ Canaid::Permissions.register_for(Project) do end end + can :read_project_users do |user, project| + project.permission_granted?(user, ProjectPermissions::USERS_READ) + end + + can :read_project_activities do |user, project| + project.permission_granted?(user, ProjectPermissions::ACTIVITIES_READ) + end + can :manage_project_users do |user, project| project.permission_granted?(user, ProjectPermissions::USERS_MANAGE) end @@ -58,10 +66,6 @@ Canaid::Permissions.register_for(Project) do project.permission_granted?(user, ProjectPermissions::COMMENTS_CREATE) end - can :manage_project_comments do |user, project| - project.permission_granted?(user, ProjectPermissions::COMMENTS_MANAGE) - end - can :manage_project_tags do |user, project| project.permission_granted?(user, ProjectPermissions::MANAGE) end @@ -70,3 +74,9 @@ Canaid::Permissions.register_for(Project) do project.permission_granted?(user, ProjectPermissions::TASKS_MANAGE) end end + +Canaid::Permissions.register_for(ProjectComment) do + can :manage_project_comment do |user, comment| + comment.project.permission_granted?(user, ProjectPermissions::COMMENTS_MANAGE) + end +end diff --git a/app/permissions/result.rb b/app/permissions/result.rb index b684545db..7730a5bce 100644 --- a/app/permissions/result.rb +++ b/app/permissions/result.rb @@ -7,6 +7,7 @@ Canaid::Permissions.register_for(Result) do can :manage_result do |user, result| !result.archived? && + !result.my_module.archived_branch? && result.unlocked?(result) && result.my_module.permission_granted?(user, MyModulePermissions::RESULTS_MANAGE) end @@ -24,8 +25,7 @@ Canaid::Permissions.register_for(ResultComment) do %i(manage_result_comment) .each do |perm| can perm do |_, comment| - my_module = ::PermissionsUtil.get_comment_module(comment) - !my_module.archived_branch? + !comment.result.my_module.archived_branch? end end @@ -33,7 +33,7 @@ Canaid::Permissions.register_for(ResultComment) do # result: update/delete comment # step: update/delete comment can :manage_result_comment do |user, comment| - my_module = ::PermissionsUtil.get_comment_module(comment) + my_module = comment.result.my_module (comment.user == user && my_module.permission_granted?(user, MyModulePermissions::RESULTS_COMMENTS_MANAGE_OWN)) || my_module.permission_granted?(user, MyModulePermissions::RESULTS_COMMENTS_MANAGE) end diff --git a/app/services/experiments/move_to_project_service.rb b/app/services/experiments/move_to_project_service.rb index b35a1c01c..9a8688224 100644 --- a/app/services/experiments/move_to_project_service.rb +++ b/app/services/experiments/move_to_project_service.rb @@ -62,12 +62,11 @@ module Experiments return false end - if !@exp.moveable_projects(@user).include?(@project) + if @exp.movable_projects(@user).include?(@project) + true + else @errors[:target_project_not_valid] = ['Experiment cannot be moved to this project'] - false - else - true end end diff --git a/app/services/experiments_overview_service.rb b/app/services/experiments_overview_service.rb index b27e1fd61..8639445b9 100644 --- a/app/services/experiments_overview_service.rb +++ b/app/services/experiments_overview_service.rb @@ -39,10 +39,11 @@ class ExperimentsOverviewService 'AND active_tasks.archived = FALSE') .joins('LEFT OUTER JOIN my_modules AS active_completed_tasks ON active_completed_tasks.experiment_id '\ '= experiments.id AND active_completed_tasks.archived = FALSE AND active_completed_tasks.state = 1') + .readable_by_user(@user) .select('experiments.*') .select('COUNT(DISTINCT active_tasks.id) AS task_count') .select('COUNT(DISTINCT active_completed_tasks.id) AS completed_task_count') - .group('experiments.id') + .group('experiments.id, user_assignments.id, user_roles.id') end def filter_records(records) diff --git a/app/services/report_actions/report_content.rb b/app/services/report_actions/report_content.rb index d1a4965be..ff5cdef20 100644 --- a/app/services/report_actions/report_content.rb +++ b/app/services/report_actions/report_content.rb @@ -68,7 +68,7 @@ module ReportActions def generate_experiment_content(experiment_id, my_module_ids) experiment = Experiment.find_by(id: experiment_id) - return if !experiment && !can_read_experiment?(experiment, @user) + return if !experiment && !can_read_experiment?(@user, experiment) experiment_element = save_element!({ 'experiment_id' => experiment.id }, :experiment, nil) generate_my_modules_content(experiment, experiment_element, my_module_ids) diff --git a/app/services/templates_service.rb b/app/services/templates_service.rb index b9346f321..11f2722d2 100644 --- a/app/services/templates_service.rb +++ b/app/services/templates_service.rb @@ -20,7 +20,8 @@ class TemplatesService tmpl_project = team.projects.create!( name: Constants::TEMPLATES_PROJECT_NAME, visibility: :visible, - template: true + template: true, + created_by: team.created_by ) tmpl_project.user_projects.create!(user: team.created_by, role: 'owner') end diff --git a/app/views/projects/show/_experiment_actions_dropdown.html.erb b/app/views/projects/show/_experiment_actions_dropdown.html.erb index 04cc9651f..c5768f46a 100644 --- a/app/views/projects/show/_experiment_actions_dropdown.html.erb +++ b/app/views/projects/show/_experiment_actions_dropdown.html.erb @@ -64,7 +64,7 @@ <% end %> - <% if can_manage_experiment_access?(experiment) %> + <% if can_manage_experiment_users?(experiment) %>