From 40355ae6c8b27e797ce3989ff11105394434eeea Mon Sep 17 00:00:00 2001 From: Martin Artnik Date: Mon, 26 Aug 2024 11:21:37 +0200 Subject: [PATCH 1/4] Generalize team sharing logic, implement sharing for storage locations [SCI-10865] --- app/controllers/repositories_controller.rb | 14 ---- .../storage_locations_controller.rb | 16 +--- .../team_shared_objects_controller.rb | 76 +++++++++++++++++ app/javascript/vue/repositories/table.vue | 9 +- .../share.vue => shared/share_modal.vue} | 44 +++++----- .../vue/storage_locations/table.vue | 26 +++++- app/models/concerns/shareable.rb | 82 +++++++++++++++++++ app/models/repository.rb | 58 +------------ app/models/storage_location.rb | 1 + app/permissions/storage_location.rb | 29 +++++++ .../concerns/shareable_serializer.rb | 42 ++++++++++ .../lists/repository_serializer.rb | 44 ++-------- .../lists/storage_location_serializer.rb | 7 +- app/serializers/shareable_team_serializer.rb | 8 +- .../lists/storage_locations_service.rb | 2 +- .../toolbars/storage_locations_service.rb | 14 +++- config/locales/en.yml | 18 ++-- config/routes.rb | 12 +++ 18 files changed, 338 insertions(+), 164 deletions(-) create mode 100644 app/controllers/team_shared_objects_controller.rb rename app/javascript/vue/{repositories/modals/share.vue => shared/share_modal.vue} (67%) create mode 100644 app/models/concerns/shareable.rb create mode 100644 app/permissions/storage_location.rb create mode 100644 app/serializers/concerns/shareable_serializer.rb diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 4d7895c0c..2f562a5ca 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -21,7 +21,6 @@ class RepositoriesController < ApplicationController before_action :check_manage_permissions, only: %i(rename_modal update) before_action :check_delete_permissions, only: %i(destroy destroy_modal) before_action :check_archive_permissions, only: %i(archive restore) - before_action :check_share_permissions, only: :share_modal before_action :check_create_permissions, only: %i(create_modal create) before_action :check_copy_permissions, only: %i(copy_modal copy) before_action :set_inline_name_editing, only: %i(show) @@ -111,15 +110,6 @@ class RepositoriesController < ApplicationController } end - def share_modal - render json: { html: render_to_string(partial: 'share_repository_modal', formats: :html) } - end - - def shareable_teams - teams = current_user.teams.order(:name) - [@repository.team] - render json: teams, each_serializer: ShareableTeamSerializer, repository: @repository - end - def hide_reminders # synchronously hide currently visible reminders if params[:visible_reminder_repository_row_ids].present? @@ -532,10 +522,6 @@ class RepositoriesController < ApplicationController render_403 unless can_delete_repository?(@repository) end - def check_share_permissions - render_403 unless can_share_repository?(@repository) - end - def repository_params params.require(:repository).permit(:name) end diff --git a/app/controllers/storage_locations_controller.rb b/app/controllers/storage_locations_controller.rb index 49c0375a1..a506668eb 100644 --- a/app/controllers/storage_locations_controller.rb +++ b/app/controllers/storage_locations_controller.rb @@ -101,7 +101,7 @@ class StorageLocationsController < ApplicationController actions: Toolbars::StorageLocationsService.new( current_user, - storage_location_ids: JSON.parse(params[:items]).map { |i| i['id'] } + storage_location_ids: JSON.parse(params[:items]).pluck('id') ).actions } end @@ -114,7 +114,7 @@ class StorageLocationsController < ApplicationController def storage_location_params params.permit(:id, :parent_id, :name, :container, :description, - metadata: [:display_type, dimensions: [], parent_coordinations: []]) + metadata: [:display_type, { dimensions: [], parent_coordinations: [] }]) end def move_params @@ -127,11 +127,7 @@ class StorageLocationsController < ApplicationController end def check_read_permissions - if @storage_location.container - render_403 unless can_read_storage_location_containers?(current_team) - else - render_403 unless can_read_storage_locations?(current_team) - end + render_403 unless can_read_storage_location?(@storage_location) end def check_create_permissions @@ -143,11 +139,7 @@ class StorageLocationsController < ApplicationController end def check_manage_permissions - if @storage_location.container - render_403 unless can_manage_storage_location_containers?(current_team) - else - render_403 unless can_manage_storage_locations?(current_team) - end + render_403 unless can_manage_storage_location?(@storage_location) end def set_breadcrumbs_items diff --git a/app/controllers/team_shared_objects_controller.rb b/app/controllers/team_shared_objects_controller.rb new file mode 100644 index 000000000..0fb70b234 --- /dev/null +++ b/app/controllers/team_shared_objects_controller.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +class TeamSharedObjectsController < ApplicationController + before_action :load_vars + before_action :check_sharing_permissions + + def update + ActiveRecord::Base.transaction do + # Global share + if params[:select_all_teams] + @model.update!(permission_level: params[:select_all_write_permission] ? :shared_write : :shared_read) + @model.team_shared_objects.each(&:destroy!) + next + end + + # Share to specific teams + params[:team_share_params].each do |t| + @model.update!(permission_level: :not_shared) if @model.globally_shareable? + @model.team_shared_objects.find_or_initialize_by(team_id: t['id']).update!( + permission_level: t['private_shared_with_write'] ? :shared_write : :shared_read + ) + end + + # Unshare + @model.team_shared_objects.where.not( + team_id: params[:team_share_params].filter { |t| t['private_shared_with'] }.pluck('id') + ).each(&:destroy!) + end + end + + def shareable_teams + teams = current_user.teams.order(:name) - [@model.team] + render json: teams, each_serializer: ShareableTeamSerializer, model: @model + end + + private + + def load_vars + case params[:object_type] + when 'Repository' + @model = current_team.repositories.find_by(id: params[:object_id]) + when 'StorageLocation' + @model = current_team.storage_locations.find_by(id: params[:object_id]) + end + + render_404 unless @model + end + + def create_params + params.permit(:team_id, :object_type, :object_id, :target_team_id, :permission_level) + end + + def destroy_params + params.permit(:team_id, :id) + end + + def update_params + params.permit(permission_changes: {}, share_team_ids: [], write_permissions: []) + end + + def check_sharing_permissions + render_403 unless public_send("can_share_#{@model.model_name.param_key}?", @model) + render_403 if !@model.shareable_write? && update_params[:write_permissions].present? + end + + def share_all_params + { + shared_with_all: params[:select_all_teams].present?, + shared_permissions_level: params[:select_all_write_permission].present? ? 'shared_write' : 'shared_read' + } + end + + def log_activity(type_of, team_shared_object) + # log activity logic + end +end diff --git a/app/javascript/vue/repositories/table.vue b/app/javascript/vue/repositories/table.vue index ade32b122..50e8f52d4 100644 --- a/app/javascript/vue/repositories/table.vue +++ b/app/javascript/vue/repositories/table.vue @@ -50,9 +50,10 @@ :repository="duplicateRepository" @close="duplicateRepository = null" @duplicate="updateTable" /> - @@ -66,7 +67,7 @@ import ExportRepositoryModal from './modals/export.vue'; import NewRepositoryModal from './modals/new.vue'; import EditRepositoryModal from './modals/edit.vue'; import DuplicateRepositoryModal from './modals/duplicate.vue'; -import ShareRepositoryModal from './modals/share.vue'; +import ShareObjectModal from '../shared/share_modal.vue'; import DataTable from '../shared/datatable/table.vue'; export default { @@ -78,7 +79,7 @@ export default { NewRepositoryModal, EditRepositoryModal, DuplicateRepositoryModal, - ShareRepositoryModal + ShareObjectModal }, props: { dataSource: { diff --git a/app/javascript/vue/repositories/modals/share.vue b/app/javascript/vue/shared/share_modal.vue similarity index 67% rename from app/javascript/vue/repositories/modals/share.vue rename to app/javascript/vue/shared/share_modal.vue index 457c49d77..802bcd207 100644 --- a/app/javascript/vue/repositories/modals/share.vue +++ b/app/javascript/vue/shared/share_modal.vue @@ -7,29 +7,29 @@