Merge pull request #4107 from okriuchykhin/ok_SCI_6821

Update the exiting permissions helpers so they will check new permissions [SCI-6821]
This commit is contained in:
Alex Kriuchykhin 2022-05-24 10:51:12 +02:00 committed by GitHub
commit 4436809115
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 70 additions and 132 deletions

View file

@ -78,7 +78,7 @@ module ClientApi
def check_update_team_permission
@team = Team.find_by_id(params[:team_id])
unless can_update_team?(@team)
unless can_manage_team?(@team)
respond_422(t('client_api.teams.update_permission_error'))
end
end

View file

@ -107,7 +107,7 @@ class ProjectFoldersController < ApplicationController
project_folders = current_team.project_folders.where(id: params[:project_folders_ids])
counter = 0
project_folders.each do |folder|
next if folder.projects.exists? || folder.project_folders.exists? || !can_update_team?(current_team)
next if folder.projects.exists? || folder.project_folders.exists? || !can_manage_team?(current_team)
folder.transaction do
log_activity(:delete_project_folder, folder, project_folder: folder.id)
@ -158,7 +158,7 @@ class ProjectFoldersController < ApplicationController
end
def check_manage_permissions
render_403 unless can_update_team?(current_team)
render_403 unless can_manage_team?(current_team)
end
def move_projects(destination_folder)

View file

@ -389,7 +389,7 @@ class ProjectsController < ApplicationController
end
def set_folder_inline_name_editing
return if !can_update_team?(current_team) || @current_folder.nil?
return if !can_manage_team?(current_team) || @current_folder.nil?
@inline_editable_title_config = {
name: 'title',

View file

@ -143,7 +143,7 @@ module Users
def load_team
@team = Team.find_by_id(params[:id])
render_403 unless can_update_team?(@team)
render_403 unless can_manage_team?(@team)
end
def create_params

View file

@ -1,7 +1,7 @@
module TeamsHelper
# resets the current team if needed
def current_team_switch(team)
if team != current_team && current_user.is_member_of_team?(team)
if team != current_team && current_user.member_of_team?(team)
current_user.current_team_id = team.id
current_user.save
update_current_team

View file

@ -10,7 +10,7 @@
If you need to specific model you have to specify it in the connect method
like the example below:
>
> Permissions.connect(MyComponent, ["can_update_team", "can_read_team"], "Team");
> Permissions.connect(MyComponent, ["can_manage_team", "can_read_team"], "Team");
>
In case your component is connected to Redux or some other HOC you can simply

View file

@ -1,44 +0,0 @@
require 'aspector'
module User::TeamRoles
extend ActiveSupport::Concern
aspector do
# Check if user is member of team
around %i(
is_member_of_team?
is_admin_of_team?
is_normal_user_of_team?
is_normal_user_or_admin_of_team?
is_guest_of_team?
) do |proxy, *args, &block|
if args[0]
@user_team = args[0]&.user_teams&.find { |ut| ut.user == self }
@user_team ? proxy.call(*args, &block) : false
else
false
end
end
end
def is_member_of_team?(team)
# This is already checked by aspector, so just return true
true
end
def is_admin_of_team?(team)
@user_team.admin?
end
def is_normal_user_of_team?(team)
@user_team.normal_user?
end
def is_normal_user_or_admin_of_team?(team)
@user_team.normal_user? or @user_team.admin?
end
def is_guest_of_team?(team)
@user_team.guest?
end
end

View file

@ -58,7 +58,7 @@ class Project < ApplicationRecord
reject_if: :all_blank
scope :visible_to, (lambda do |user, team|
unless user.is_admin_of_team?(team)
unless can_manage_team?(team)
left_outer_joins(user_assignments: :user_role)
.where(user_assignments: { user: user })
.where('? = ANY(user_roles.permissions)', ProjectPermissions::READ)

View file

@ -4,7 +4,6 @@ class User < ApplicationRecord
include SearchableModel
include SettingsModel
include VariablesModel
include User::TeamRoles
include TeamBySubjectModel
include InputSanitizeHelper
include ActiveStorageConcerns
@ -389,6 +388,10 @@ class User < ApplicationRecord
.take
end
def member_of_team?(team)
team.user_assignments.exists?(user: self)
end
# Search all active users for username & email. Can
# also specify which team to ignore.
def self.search(

View file

@ -20,7 +20,7 @@ Canaid::Permissions.register_for(Project) do
export_project)
.each do |perm|
can perm do |user, project|
user.is_admin_of_team?(project.team) || project.permission_granted?(user, ProjectPermissions::READ)
project.permission_granted?(user, ProjectPermissions::READ)
end
end
@ -46,7 +46,7 @@ Canaid::Permissions.register_for(Project) do
end
can :manage_project_users do |user, project|
user.is_admin_of_team?(project.team) || project.permission_granted?(user, ProjectPermissions::USERS_MANAGE)
project.permission_granted?(user, ProjectPermissions::USERS_MANAGE)
end
can :archive_project do |user, project|

View file

@ -16,7 +16,6 @@ Canaid::Permissions.register_for(Repository) do
%i(manage_repository
create_repository_rows
manage_repository_rows
update_repository_rows
delete_repository_rows
create_repository_columns)
.each do |perm|
@ -27,14 +26,14 @@ Canaid::Permissions.register_for(Repository) do
# repository: update, delete
can :manage_repository do |user, repository|
user.is_admin_of_team?(repository.team) unless repository.shared_with?(user.current_team)
!repository.shared_with?(user.current_team) && repository.permission_granted?(user, RepositoryPermissions::MANAGE)
end
# repository: archive, restore
can :archive_repository do |user, repository|
next false if repository.is_a?(BmtRepository)
!repository.shared_with?(user.current_team) && user.is_admin_of_team?(repository.team)
!repository.shared_with?(user.current_team) && repository.permission_granted?(user, RepositoryPermissions::MANAGE)
end
# repository: destroy
@ -44,17 +43,17 @@ Canaid::Permissions.register_for(Repository) do
# repository: share
can :share_repository do |user, repository|
user.is_admin_of_team?(repository.team) unless repository.shared_with?(user.current_team)
can_manage_repository?(user, repository)
end
# repository: make a snapshot with assigned rows
can :create_repository_snapshot do |user, repository|
user.is_normal_user_or_admin_of_team?(repository.team)
can_read_repository?(user, repository)
end
# repository: delete a snapshot with assigned rows
can :delete_repository_snapshot do |user, repository|
user.is_normal_user_or_admin_of_team?(repository.team)
can_manage_repository?(user, repository)
end
# repository: create/import record
@ -63,38 +62,36 @@ Canaid::Permissions.register_for(Repository) do
next false if repository.archived?
if repository.shared_with?(user.current_team)
repository.shared_with_write?(user.current_team) && user.is_normal_user_or_admin_of_team?(user.current_team)
elsif user.teams.include?(repository.team)
user.is_normal_user_or_admin_of_team?(repository.team)
repository.shared_with_write?(user.current_team) &&
repository.permission_granted?(user, RepositoryPermissions::ROWS_CREATE)
else
repository.permission_granted?(user, RepositoryPermissions::ROWS_CREATE)
end
end
can :manage_repository_assets do |user, repository|
can_create_repository_rows?(user, repository)
repository.permission_granted?(user, RepositoryPermissions::ROWS_UPDATE)
end
# repository: update/delete records
can :manage_repository_rows do |user, repository|
can_create_repository_rows?(user, repository)
end
can :update_repository_rows do |user, repository|
can_manage_repository_rows?(user, repository)
repository.permission_granted?(user, RepositoryPermissions::ROWS_UPDATE)
end
can :delete_repository_rows do |user, repository|
can_manage_repository_rows?(user, repository)
repository.permission_granted?(user, RepositoryPermissions::ROWS_DELETE)
end
# repository: create field
can :create_repository_columns do |user, repository|
can_create_repository_rows?(user, repository) unless repository.shared_with?(user.current_team)
!repository.shared_with?(user.current_team) &&
repository.permission_granted?(user, RepositoryPermissions::COLUMNS_CREATE)
end
# repository: create/update/delete filters
can :manage_repository_filters do |user, repository|
((repository.team == user.current_team) && user.is_normal_user_or_admin_of_team?(repository.team)) ||
(repository.shared_with_write?(user.current_team) && user.is_normal_user_or_admin_of_team?(user.current_team))
((repository.team == user.current_team) && can_manage_team?(user, repository.team)) ||
(repository.shared_with_write?(user.current_team) && can_manage_team?(user, user.current_team))
end
can :manage_repository_stock do |user, repository|

View file

@ -3,65 +3,64 @@ Canaid::Permissions.register_for(Team) do
# read protocols
#
can :read_team do |user, team|
user.is_member_of_team?(team)
user.member_of_team?(team)
end
# team: update
can :update_team do |user, team|
user.is_admin_of_team?(team)
can :manage_team do |user, team|
team.permission_granted?(user, TeamPermissions::MANAGE)
end
# team: assign/unassing user, change user role
can :manage_team_users do |user, team|
user.is_admin_of_team?(team)
team.permission_granted?(user, TeamPermissions::USERS_MANAGE)
end
# team: invite new users to the team
can :invite_team_users do
true
can :invite_team_users do |user, team|
can_manage_team_users?(user, team)
end
# project_folder: create
can :create_project_folders do |user, team|
user.is_admin_of_team?(team)
can_manage_team?(user, team)
end
# project: create
can :create_projects do |user, team|
user.is_normal_user_or_admin_of_team?(team)
team.permission_granted?(user, TeamPermissions::PROJECTS_CREATE)
end
# protocol in repository: create, import
can :create_protocols_in_repository do |user, team|
user.is_normal_user_or_admin_of_team?(team)
team.permission_granted?(user, TeamPermissions::PROTOCOLS_CREATE)
end
can :manage_bmt_filters do |user, team|
user.is_normal_user_or_admin_of_team?(team)
can_manage_team?(user, team)
end
# repository: create, copy
can :create_repositories do |user, team|
within_limits = Repository.within_global_limits?
within_limits = Repository.within_team_limits?(team) if within_limits
within_limits && user.is_admin_of_team?(team)
within_limits && team.permission_granted?(user, TeamPermissions::INVENTORIES_CREATE)
end
# this permission is scattered around the application
# if you want to make changes here keep in mind to check/change the
# SQL view that lists reports in index page:
# - db/views/datatables_reports_v01.sql
# - check the model app/models/views/datatables/datatables_report.rb
# - check visible_by method in Project model
can :manage_reports do |user, team|
user.is_normal_user_or_admin_of_team?(team)
can_manage_team?(user, team)
end
end
Canaid::Permissions.register_for(ProjectFolder) do
# ProjectFolder: delete
can :delete_project_folder do |user, project_folder|
user.is_admin_of_team?(project_folder.team) &&
can_manage_team?(user, team) &&
project_folder.projects.none? &&
project_folder.project_folders.none?
end
@ -70,7 +69,7 @@ end
Canaid::Permissions.register_for(Protocol) do
# protocol in repository: read, export, read step, read/download step asset
can :read_protocol_in_repository do |user, protocol|
user.is_member_of_team?(protocol.team) &&
user.member_of_team?(protocol.team) &&
(protocol.in_repository_public? ||
protocol.in_repository_private? && user == protocol.added_by)
end
@ -78,21 +77,16 @@ Canaid::Permissions.register_for(Protocol) do
# protocol in repository: update, create/update/delete/reorder step,
# toggle private/public visibility, archive
can :manage_protocol_in_repository do |user, protocol|
protocol.in_repository_active? &&
user.is_normal_user_or_admin_of_team?(protocol.team) &&
user == protocol.added_by
protocol.in_repository_active? && protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
end
# protocol in repository: restore
can :restore_protocol_in_repository do |user, protocol|
protocol.in_repository_archived? &&
user.is_normal_user_or_admin_of_team?(protocol.team) &&
user == protocol.added_by
protocol.in_repository_archived? && protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
end
# protocol in repository: copy
can :clone_protocol_in_repository do |user, protocol|
can_read_protocol_in_repository?(user, protocol) &&
can_create_protocols_in_repository?(user, protocol.team)
can_read_protocol_in_repository?(user, protocol) && can_create_protocols_in_repository?(user, protocol.team)
end
end

View file

@ -83,9 +83,7 @@
<div class="widget-placeholder">
<p class="widget-placeholder-title team"><%= I18n.t('dashboard.current_tasks.no_tasks.team_tasks.title') %></p>
<p class="widget-placeholder-title assigned"><%= I18n.t('dashboard.current_tasks.no_tasks.assigned_tasks.title') %></p>
<% unless current_user.is_guest_of_team?(current_team) %>
<p class="widget-placeholder-description"><%= I18n.t('dashboard.current_tasks.no_tasks.assigned_tasks.description') %></p>
<% end %>
<p class="widget-placeholder-description"><%= I18n.t('dashboard.current_tasks.no_tasks.assigned_tasks.description') %></p>
</div>
</template>

View file

@ -1,12 +1,10 @@
<% unless current_user.is_guest_of_team?(current_team) %>
<div class="quick-start-buttons">
<div class="new-task btn btn-secondary"><i class="fas fa-plus"></i><%= t("dashboard.quick_start.new_task") %></div>
<%= link_to protocols_path, {class: "new-protocol btn btn-secondary"} do %>
<i class="fas fa-edit"></i><%= t("dashboard.quick_start.new_protocol") %>
<% end %>
<%= link_to new_report_path, {class: "new-report btn btn-secondary"} do %>
<i class="fas fa-clipboard-check"></i><%= t("dashboard.quick_start.new_report") %>
<% end %>
</div>
<%= render "create_task_modal" %>
<% end %>
<div class="quick-start-buttons">
<div class="new-task btn btn-secondary"><i class="fas fa-plus"></i><%= t("dashboard.quick_start.new_task") %></div>
<%= link_to protocols_path, {class: "new-protocol btn btn-secondary"} do %>
<i class="fas fa-edit"></i><%= t("dashboard.quick_start.new_protocol") %>
<% end %>
<%= link_to new_report_path, {class: "new-report btn btn-secondary"} do %>
<i class="fas fa-clipboard-check"></i><%= t("dashboard.quick_start.new_report") %>
<% end %>
</div>
<%= render "create_task_modal" %>

View file

@ -26,12 +26,7 @@
<template id="recent-work-no-results-template">
<div class="widget-placeholder">
<% if current_user.is_guest_of_team?(current_team) %>
<p class="widget-placeholder-title"><%= t('dashboard.recent_work.no_results_guest.title') %></p>
<p class="widget-placeholder-description"><%= t('dashboard.recent_work.no_results_guest.description') %></p>
<% else %>
<p class="widget-placeholder-title"><%= t('dashboard.recent_work.no_results.title') %></p>
<p class="widget-placeholder-description"><%= t('dashboard.recent_work.no_results.description') %></p>
<% end %>
<p class="widget-placeholder-title"><%= t('dashboard.recent_work.no_results.title') %></p>
<p class="widget-placeholder-description"><%= t('dashboard.recent_work.no_results.description') %></p>
</div>
</template>

View file

@ -8,7 +8,7 @@
<div class="modal-body"></div>
<div class="modal-footer">
<span class="pull-left">
<% if current_user.is_admin_of_team?(@experiment.project.team) %>
<% if can_manage_team_users(@experiment.project.team) %>
<%= link_to t("experiments.canvas.full_zoom.modal_manage_users.invite_users_link"), team_path(@experiment.project.team.id) %>
<span><%=t "experiments.canvas.full_zoom.modal_manage_users.invite_users_details", team: @experiment.project.team.name %></span>
<% else %>

View file

@ -1,11 +1,11 @@
<div class="card folder-card"
data-id="<%= folder.id %>"
data-edit-url="<%= edit_project_folder_path(folder) %>"
data-editable="<%= can_update_team?(current_team) %>"
data-moveable="<%= can_update_team?(current_team) %>"
data-editable="<%= can_manage_team?(current_team) %>"
data-moveable="<%= can_manage_team?(current_team) %>"
data-archivable="false"
data-restorable="false"
data-deletable="<%= can_delete_project_folder?(folder) && can_update_team?(current_team) %>">
data-deletable="<%= can_delete_project_folder?(folder) && can_manage_team?(current_team) %>">
<div class="checkbox-cell table-cell">
<div class="sci-checkbox-container">
<input value="1" type="checkbox" class="sci-checkbox folder-card-selector">

View file

@ -2,7 +2,7 @@
data-id="<%= project.id %>"
data-edit-url="<%= edit_project_path(project) %>"
data-editable="<%= can_manage_project?(project) %>"
data-moveable="<%= can_update_team?(current_team) %>"
data-moveable="<%= can_manage_team?(current_team) %>"
data-archivable="<%= project.active? && can_archive_project?(project) %>"
data-restorable="<%= project.archived? && can_restore_project?(project) %>">
<div class="checkbox-cell table-cell">

View file

@ -16,7 +16,7 @@
</div>
<% end %>
<div class="content-pane flexible empty-repositories" data-readonly="<%= !current_user.is_admin_of_team?(current_team) %>">
<div class="content-pane flexible empty-repositories" data-readonly="<%= !can_manage_team?(current_team) %>">
<div class="content-header">
<h1 data-view-mode="active"><%= t('libraries.index.head_title') %></h1>
</div>

View file

@ -8,7 +8,7 @@
<%= render partial: "sidebar", locals: { repositories: @repositories, archived: params[:archived] } %>
<% end %>
<div class="content-pane flexible <%= params[:archived] ? :archived : :active %> repositories-index"
data-readonly="<%= !current_user.is_admin_of_team?(current_team) %>">
data-readonly="<%= !can_manage_team?(current_team) %>">
<div class="content-header">
<div class="title-row">
<h1 data-view-mode="active"><%= t('libraries.index.head_title') %></h1>

View file

@ -1,6 +1,6 @@
<% if can_manage_repository_rows?(@repository) %>
<span id="editDeleteCopy" data-toggle="buttons" style="display:none">
<%if can_update_repository_rows?(@repository) %>
<% if can_manage_repository_rows?(@repository) %>
<button type="button" title="<%= t('repositories.show.button_tooltip.edit') %>"
class="btn btn-light editAdd auto-shrink-button"
id="editRepositoryRecord" disabled data-view-mode="active">

View file

@ -16,7 +16,7 @@
<!-- TITLE -->
<h1 id="team-name" class="settings-team-name" data-current-team="<%= current_team == @team %>">
<% if can_update_team?(@team) %>
<% if can_manage_team?(@team) %>
<%= render partial: "shared/inline_editing",
locals: {
initial_value: @team.name,
@ -57,7 +57,7 @@
</div>
<div class="team-description">
<% if can_update_team?(@team) %>
<% if can_manage_team?(@team) %>
<div
class="inline-init-handler"
data-field-to-update="description"

View file

@ -74,9 +74,6 @@ en:
no_results:
title: "You have not worked on anything recently."
description: "All tasks, projects, inventories protocols and reports, you last worked on will appear here, when you make some changes."
no_results_guest:
title: "No recent work."
description: "As a guest in this team you cannot make or change anything."
modes:
all: "All"
projects: "PROJECTS"