From 2ac1107e97efeda4fd62c9c3d1c885a092aa8cf6 Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Thu, 22 Aug 2024 15:16:37 +0200 Subject: [PATCH 1/5] [#57286] refactored nextcloud command for set_permission - https://community.openproject.org/work_packages/57286 - adapted set_permission interface with contracted input data --- .../inputs/set_permissions.rb | 6 +- .../inputs/set_permissions_contract.rb | 13 +- .../nextcloud/set_permissions_command.rb | 53 ++++--- .../nextcloud_managed_folder_sync_service.rb | 134 ++++++++++-------- .../lib/open_project/storages/engine.rb | 18 +-- .../inputs/set_permissions_spec.rb | 18 ++- 6 files changed, 148 insertions(+), 94 deletions(-) diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions.rb index 01988b79c525..41aa5f129047 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions.rb @@ -33,7 +33,8 @@ module Peripherals module StorageInteraction module Inputs # user_permissions - A list of user specific file permissions. - # IMPORTANT: the user ids are considered to be the ids of the remote identities. + # IMPORTANT: the user ids are considered to be the ids of the remote identities. If user permissions should be + # set via a group, a `group_id` must be provided instead of a `user_id`. # Example: # [ # {user_id: "d6e00f6d-1ae7-43e6-b0af-15d99a56d4ce", permissions: [ :read_files, @@ -41,7 +42,8 @@ module Inputs # :create_files, # :delete_files, # :share_files ]}, - # {user_id: "f6e00f6d-1ae7-43e6-b0af-15d99a56d4ce", permissions: [:read_files, :write_files]} + # {user_id: "f6e00f6d-1ae7-43e6-b0af-15d99a56d4ce", permissions: [:read_files, :write_files]}, + # {group_id: "fee9cd49-17e2-4430-9235-2060e7372568", permissions: [:read_files]}, # ] SetPermissions = Data.define(:file_id, :user_permissions) do private_class_method :new diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions_contract.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions_contract.rb index e866eb2ffc74..e63f95b7fb72 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions_contract.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/inputs/set_permissions_contract.rb @@ -36,10 +36,19 @@ class SetPermissionsContract < Dry::Validation::Contract params do required(:file_id).filled(:string) required(:user_permissions).array(:hash) do - required(:user_id).filled(:string) - required(:permissions).array(:symbol, included_in?: OpenProject::Storages::Engine.permissions) + optional(:user_id).filled(:string) + optional(:group_id).filled(:string) + required(:permissions) + .array(:symbol, included_in?: OpenProject::Storages::Engine.external_file_permissions) end end + + rule(:user_permissions).each do + both = value.key?(:user_id) && value.key?(:group_id) + none = !value.key?(:user_id) && !value.key?(:group_id) + + key.failure("must have either user_id or group_id") if both || none + end end end end diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command.rb index d2a138e2f474..e91b89135814 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command.rb @@ -32,16 +32,22 @@ module Storages module Peripherals module StorageInteraction module Nextcloud - # TODO: refactor to be consistent with OneDrive::SetPermissionsCommand interface - # And streamline test cases. class SetPermissionsCommand include TaggedLogging using ServiceResultRefinements + PERMISSIONS_MAP = { read_files: 1, write_files: 2, create_files: 4, delete_files: 8, share_files: 16 }.freeze + PERMISSIONS_KEYS = OpenProject::Storages::Engine.external_file_permissions SUCCESS_XPATH = "/d:multistatus/d:response/d:propstat[d:status[text() = 'HTTP/1.1 200 OK']]/d:prop/nc:acl-list" - def self.call(storage:, auth_strategy:, path:, permissions:) - new(storage).call(auth_strategy:, path:, permissions:) + # Instantiates the command and executes it. + # + # @param storage [Storage] The storage to interact with. + # @param auth_strategy [AuthenticationStrategy] The authentication strategy to use. + # @param input_data [Inputs::SetPermissions] The data needed for setting permissions, containing the file id + # and the permissions for an array of users. + def self.call(storage:, auth_strategy:, input_data:) + new(storage).call(auth_strategy:, input_data:) end def initialize(storage) @@ -49,25 +55,30 @@ def initialize(storage) end # rubocop:disable Metrics/AbcSize - def call(auth_strategy:, path:, permissions:) - validate_input_data(path).on_failure { return _1 } - + def call(auth_strategy:, input_data:) username = Util.origin_user_id(caller: self.class, storage: @storage, auth_strategy:) .on_failure { return _1 } .result + permissions = parse_permission_mask(input_data.user_permissions) + Authentication[auth_strategy].call(storage: @storage) do |http| with_tagged_logger do - info "Setting permissions #{permissions.inspect} on #{path}" + info "Getting the folder information" + folder_info = FileInfoQuery.call(storage: @storage, auth_strategy:, file_id: input_data.file_id) + .on_failure { return _1 } + .result + + info "Setting permissions #{permissions.inspect} on #{folder_info.location}" body = request_xml_body(permissions[:groups], permissions[:users]) # This can raise KeyErrors, we probably should just default to empty Arrays. - response = http - .request( - "PROPPATCH", - UrlBuilder.url(@storage.uri, "remote.php/dav/files", username, path), - xml: body - ) + response = http.request("PROPPATCH", + UrlBuilder.url(@storage.uri, + "remote.php/dav/files", + username, + CGI.unescape(folder_info.location)), + xml: body) handle_response(response) end @@ -78,11 +89,15 @@ def call(auth_strategy:, path:, permissions:) private - def validate_input_data(path) - if path.blank? - ServiceResult.failure(errors: StorageError.new(code: :invalid_path)) - else - ServiceResult.success + def parse_permission_mask(user_permissions) + user_permissions.each_with_object({ groups: {}, users: {} }) do |entry, aggregate| + if entry.key?(:user_id) + aggregate[:users][entry[:user_id]] = + PERMISSIONS_MAP.values_at(*(PERMISSIONS_KEYS & entry[:permissions])).sum + else + aggregate[:groups][entry[:group_id]] = + PERMISSIONS_MAP.values_at(*(PERMISSIONS_KEYS & entry[:permissions])).sum + end end end diff --git a/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb b/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb index 3621ef4b3c6a..934a2ea1a4e0 100644 --- a/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb +++ b/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb @@ -32,10 +32,7 @@ module Storages class NextcloudManagedFolderSyncService < BaseService using Peripherals::ServiceResultRefinements - PERMISSIONS_MAP = { read_files: 1, write_files: 2, create_files: 4, delete_files: 8, share_files: 16 }.freeze - PERMISSIONS_KEYS = PERMISSIONS_MAP.keys.freeze - ALL_PERMISSIONS = PERMISSIONS_MAP.values.sum - NO_PERMISSIONS = 0 + FILE_PERMISSIONS = OpenProject::Storages::Engine.external_file_permissions include Injector["nextcloud.commands.create_folder", "nextcloud.commands.rename_file", "nextcloud.commands.set_permissions", "nextcloud.queries.group_users", "nextcloud.queries.file_ids", "nextcloud.authentication.userless", @@ -79,7 +76,7 @@ def prepare_remote_folders remote_folders = remote_root_folder_map(@storage.group_folder).on_failure { return _1 }.result info "Found #{remote_folders.count} remote folders" - ensure_root_folder_permissions(@storage.group_folder, @storage.group, @storage.username).on_failure { return _1 } + ensure_root_folder_permissions(remote_folders["/#{@storage.group_folder}/"]["fileid"]).on_failure { return _1 } ensure_folders_exist(remote_folders).on_success { hide_inactive_folders(remote_folders) } end @@ -89,7 +86,7 @@ def apply_permissions_to_folders remote_admins = admin_remote_identities_scope.pluck(:origin_user_id) active_project_storages_scope.where.not(project_folder_id: nil).find_each do |project_storage| - set_folders_permissions(remote_admins, project_storage) + set_folder_permissions(remote_admins, project_storage) end info "Updating user access on automatically managed project folders" @@ -129,32 +126,31 @@ def remove_users_from_remote_group(users_to_remove) end # rubocop:disable Metrics/AbcSize - def set_folders_permissions(remote_admins, project_storage) - admin_permissions = remote_admins.to_set.map do |username| - [username, ALL_PERMISSIONS] - end.unshift([@storage.username, ALL_PERMISSIONS]) + def set_folder_permissions(remote_admins, project_storage) + system_user = [{ user_id: @storage.username, permissions: FILE_PERMISSIONS }] - users_permissions = project_remote_identities(project_storage).each_with_object({}) do |identity, hash| - permissions = identity.user.all_permissions_for(project_storage.project) + admin_permissions = remote_admins.to_set.map { |username| { user_id: username, permissions: FILE_PERMISSIONS } } - hash[identity.origin_user_id] = PERMISSIONS_MAP.values_at(*(PERMISSIONS_KEYS & permissions)).sum + users_permissions = project_remote_identities(project_storage).map do |identity| + permissions = identity.user.all_permissions_for(project_storage.project) & FILE_PERMISSIONS + { user_id: identity.origin_user_id, permissions: } end - folder = project_storage.managed_project_folder_path - - command_params = { - path: folder, - permissions: { - users: admin_permissions.to_h.merge(users_permissions), - groups: { "#{@storage.group}": NO_PERMISSIONS } - } - } - - set_permissions.call(storage: @storage, auth_strategy:, **command_params).on_failure do |service_result| - log_storage_error(service_result.errors, folder:) - add_error(:set_folder_permission, service_result.errors, options: { folder: }) - end + permissions = system_user + admin_permissions + users_permissions + project_folder_id = project_storage.project_folder_id + + build_set_permissions_input_data(project_folder_id, permissions) + .either( + ->(input_data) do + set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| + log_storage_error(service_result.errors, folder: project_folder_id) + add_error(:set_folder_permission, service_result.errors, options: { folder: project_folder_id }) + end + end, + ->(failure) { log_validation_error(failure, project_folder_id:, permissions:) } + ) end + # rubocop:enable Metrics/AbcSize def project_remote_identities(project_storage) @@ -173,21 +169,29 @@ def hide_inactive_folders(remote_folders) project_folder_ids = active_project_storages_scope.pluck(:project_folder_id).compact remote_folders.except("/#{@storage.group_folder}/").each do |(path, attrs)| - next if project_folder_ids.include?(attrs["fileid"]) - - info "Hiding folder #{path} as it does not belong to any active project" - command_params = { path:, - permissions: { - users: { "#{@storage.username}": ALL_PERMISSIONS }, - groups: { "#{@storage.group}": NO_PERMISSIONS } - } } - - set_permissions.call(storage: @storage, auth_strategy:, **command_params).on_failure do |service_result| - log_storage_error(service_result.errors, folder: path, context: "hide_folder") - add_error(:hide_inactive_folders, service_result.errors, options: { path: }) - end + folder_id = attrs["fileid"] + + next if project_folder_ids.include?(folder_id) + + info "Hiding folder #{folder_id} (#{path}) as it does not belong to any active project" + permissions = [ + { user_id: @storage.username, permissions: FILE_PERMISSIONS }, + { group_id: @storage.group, permissions: [] } + ] + + build_set_permissions_input_data(folder_id, permissions) + .either( + ->(input_data) do + set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| + log_storage_error(service_result.errors, folder_id:, context: "hide_folder") + add_error(:hide_inactive_folders, service_result.errors, options: { folder_id: }) + end + end, + ->(failure) { log_validation_error(failure, folder_id:, permissions:) } + ) end end + # rubocop:enable Metrics/AbcSize def ensure_folders_exist(remote_folders) @@ -246,33 +250,41 @@ def create_remote_folder(project_storage) def audit_last_project_folder(last_project_folder, project_folder_id) ApplicationRecord.transaction do success = last_project_folder.update(origin_folder_id: project_folder_id) && - last_project_folder.project_storage.update(project_folder_id:) + last_project_folder.project_storage.update(project_folder_id:) raise ActiveRecord::Rollback unless success end end - # @param group_folder [string] name of the Group Folder in Nextcloud. - # @param username [String] username for the integration user - # @param group [String] group that the user should be part of + # rubocop:disable Metrics/AbcSize + # @param root_folder_id [String] the id of the root folder # @return [ServiceResult] - def ensure_root_folder_permissions(group_folder, username, group) - info "Setting needed permissions for user #{username} and group #{group} on #{group_folder} group folder" - - command_params = { - path: group_folder, - permissions: { - users: { username.to_sym => ALL_PERMISSIONS }, - groups: { group.to_sym => PERMISSIONS_MAP[:read_files] } - } - } - - set_permissions.call(storage: @storage, auth_strategy:, **command_params).on_failure do |service_result| - log_storage_error(service_result.errors, { folder: group_folder }) - add_error(:ensure_root_folder_permissions, service_result.errors, options: { group:, username: }).fail! - end + def ensure_root_folder_permissions(root_folder_id) + username = @storage.username + group = @storage.group + info "Setting needed permissions for user #{username} and group #{group} on the root group folder." + permissions = [ + { user_id: username, permissions: FILE_PERMISSIONS }, + { group_id: group, permissions: [:read_files] } + ] + + build_set_permissions_input_data(root_folder_id, permissions) + .either( + ->(input_data) do + set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| + log_storage_error(service_result.errors, folder: "root", root_folder_id:) + add_error(:ensure_root_folder_permissions, service_result.errors, options: { group:, username: }).fail! + end + end, + ->(failure) do + log_validation_error(failure, root_folder_id:, permissions:) + ServiceResult.failure(result: failure.errors.to_h) # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods + end + ) end + # rubocop:enable Metrics/AbcSize + def remote_root_folder_map(group_folder) info "Retrieving already existing folders under #{group_folder}" file_ids.call(storage: @storage, path: group_folder).on_failure do |service_result| @@ -281,6 +293,10 @@ def remote_root_folder_map(group_folder) end end + def build_set_permissions_input_data(file_id, user_permissions) + Peripherals::StorageInteraction::Inputs::SetPermissions.build(file_id:, user_permissions:) + end + def remote_group_users info "Retrieving users that a part of the #{@storage.group} group" group_users.call(storage: @storage, group: @storage.group) diff --git a/modules/storages/lib/open_project/storages/engine.rb b/modules/storages/lib/open_project/storages/engine.rb index 0a078bc0a26d..af789d410f67 100644 --- a/modules/storages/lib/open_project/storages/engine.rb +++ b/modules/storages/lib/open_project/storages/engine.rb @@ -38,8 +38,8 @@ module OpenProject::Storages class Engine < ::Rails::Engine - def self.permissions - @permissions ||= Storages::NextcloudManagedFolderSyncService::PERMISSIONS_KEYS + def self.external_file_permissions + %i[read_files write_files create_files delete_files share_files].freeze end # engine name is used as a default prefix for module tables when generating @@ -90,7 +90,7 @@ def self.permissions OpenProject::Notifications.subscribe( OpenProject::Events::ROLE_UPDATED ) do |payload| - if payload[:permissions_diff]&.intersect?(OpenProject::Storages::Engine.permissions) + if payload[:permissions_diff]&.intersect?(OpenProject::Storages::Engine.external_file_permissions) ::Storages::ManageStorageIntegrationsJob.debounce end end @@ -98,7 +98,7 @@ def self.permissions OpenProject::Notifications.subscribe( OpenProject::Events::ROLE_DESTROYED ) do |payload| - if payload[:permissions]&.intersect?(OpenProject::Storages::Engine.permissions) + if payload[:permissions]&.intersect?(OpenProject::Storages::Engine.external_file_permissions) ::Storages::ManageStorageIntegrationsJob.debounce end end @@ -166,7 +166,7 @@ def self.permissions "storages/project_settings/project_storage_members": %i[index] }, permissible_on: :project, dependencies: %i[] - OpenProject::Storages::Engine.permissions.each do |p| + OpenProject::Storages::Engine.external_file_permissions.each do |p| permission(p, {}, permissible_on: :project, dependencies: %i[]) end end @@ -219,10 +219,10 @@ def self.permissions prj.project_storages.each do |prj_storage| storage = prj_storage.storage hide_from_menu = !storage.configured? || - # the following check is required for ensure access modal final check being possible - # the modal waiting for read_files permission on the project folder - # otherwise polls backend until eternity - (prj_storage.project_folder_automatic? && !u.allowed_in_project?(:read_files, prj)) + # the following check is required for ensure access modal final check being possible + # the modal waiting for read_files permission on the project folder + # otherwise polls backend until eternity + (prj_storage.project_folder_automatic? && !u.allowed_in_project?(:read_files, prj)) next if hide_from_menu icon = storage.provider_type_nextcloud? ? "op-mark-nextcloud" : "file-directory" diff --git a/modules/storages/spec/common/storages/peripherals/storage_interaction/inputs/set_permissions_spec.rb b/modules/storages/spec/common/storages/peripherals/storage_interaction/inputs/set_permissions_spec.rb index f9e438a17b6e..55cd0482cafd 100644 --- a/modules/storages/spec/common/storages/peripherals/storage_interaction/inputs/set_permissions_spec.rb +++ b/modules/storages/spec/common/storages/peripherals/storage_interaction/inputs/set_permissions_spec.rb @@ -43,9 +43,14 @@ expect(described_class.build(file_id: "1337", user_permissions: [])).to be_success expect(described_class.build(file_id: "1337", user_permissions: [{ user_id: "dart_vader", permissions: [] }])).to be_success - expect(described_class.build(file_id: "1337", - user_permissions: [{ user_id: "dart_vader", - permissions: [:read_files] }])).to be_success + expect(described_class + .build( + file_id: "1337", + user_permissions: [ + { user_id: "dart_vader", permissions: %i[read_files write_files delete_files] }, + { group_id: "stormtroopers", permissions: [:read_files] } + ] + )).to be_success end it "creates a failure result for invalid input data" do @@ -60,6 +65,13 @@ user_permissions: [{ user_id: "rey", permissions: [:read] }])).to be_failure expect(described_class.build(file_id: "1337", user_permissions: [{ user_id: "rey", permissions: {} }])).to be_failure + + expect(described_class.build(file_id: "1337", user_permissions: [{ permissions: [:read_files] }])).to be_failure + expect(described_class + .build( + file_id: "1337", + user_permissions: [{ user_id: "rey", group_id: "jedi", permissions: [:read_files] }] + )).to be_failure end end end From 3efb834c028f5bc904117f41ba49001b587f292b Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Tue, 27 Aug 2024 15:59:57 +0200 Subject: [PATCH 2/5] [#57286] added unit tests for nextcloud set permission command --- .../nextcloud/internal/propfind_query.rb | 7 +- .../nextcloud/set_permissions_command_spec.rb | 152 ++++ .../one_drive/set_permissions_command_spec.rb | 2 +- .../spec/factories/storage_factory.rb | 4 +- .../set_permissions_invalid_user_id.yml | 583 ++++++++++++++ .../nextcloud/set_permissions_new.yml | 589 ++++++++++++++ .../set_permissions_not_found_folder.yml | 82 ++ .../set_permissions_replacing_permissions.yml | 753 ++++++++++++++++++ .../set_permissions_command_examples.rb | 18 + 9 files changed, 2185 insertions(+), 5 deletions(-) create mode 100644 modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb create mode 100644 modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_invalid_user_id.yml create mode 100644 modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_new.yml create mode 100644 modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_not_found_folder.yml create mode 100644 modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_replacing_permissions.yml diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/internal/propfind_query.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/internal/propfind_query.rb index 5e0bbf25f1cf..e0c31a4bfcc8 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/internal/propfind_query.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/internal/propfind_query.rb @@ -44,8 +44,7 @@ class PropfindQuery # d:getcontenttype # d:resourcetype # d:getcontentlength - # d:permissions - # d:size + # oc:permissions # oc:id # oc:fileid # oc:favorite @@ -62,6 +61,10 @@ class PropfindQuery # nc:contained-folder-count # nc:contained-file-count # nc:acl-list + # nc:inherited-acl-list + # nc:group-folder-id + # nc:acl-enabled + # nc:acl-can-manage # ].freeze def self.call(storage:, http:, username:, path:, props:) diff --git a/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb b/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb new file mode 100644 index 000000000000..6fd0509d7f1e --- /dev/null +++ b/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +#++ + +require "spec_helper" +require_module_spec_helper + +RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::SetPermissionsCommand, :webmock do + let(:user) { create(:user) } + let(:storage) { create(:nextcloud_storage_with_local_connection, :as_automatically_managed) } + let(:auth_strategy) { Storages::Peripherals::Registry.resolve("nextcloud.authentication.userless").call } + + let(:test_folder) do + Storages::Peripherals::Registry + .resolve("nextcloud.commands.create_folder") + .call(storage:, + auth_strategy:, + folder_name: "Permission Test Folder", + parent_location: Storages::Peripherals::ParentFolder.new("/VCR")) + .result + end + + it_behaves_like "set_permissions_command: basic command setup" + + context "if folder does not exists", vcr: "nextcloud/set_permissions_not_found_folder" do + let(:error_source) { Storages::Peripherals::StorageInteraction::Nextcloud::FileInfoQuery } + let(:input_data) { permission_input_data("1337", []) } + + it_behaves_like "set_permissions_command: not found" + end + + context "if no permissions exist", vcr: "nextcloud/set_permissions_new" do + let(:user_permissions) do + [ + { user_id: "m.jade@death.star", permissions: %i[read_files write_files] }, + { user_id: "admin", permissions: %i[read_files write_files create_files delete_files] } + ] + end + + it_behaves_like "set_permissions_command: creates new permissions" + end + + context "if a permission set already exist", vcr: "nextcloud/set_permissions_replacing_permissions" do + let(:previous_permissions) do + [{ user_id: "admin", permissions: %i[read_files write_files create_files delete_files] }] + end + let(:replacing_permissions) do + [{ user_id: "m.jade@death.star", permissions: %i[read_files write_files] }] + end + + it_behaves_like "set_permissions_command: replaces already set permissions" + end + + context "if a user does not exist", + skip: "When setting permissions for a user that does not exists, nextcloud's response doesn't contain the" \ + "needed information. We need to work around this by maybe having a separate request fetching ACLs " \ + "after setting them.", + vcr: "nextcloud/set_permissions_invalid_user_id" do + let(:user_permissions) do + [{ user_id: "luke_the_sky", permissions: %i[read_files write_files create_files delete_files share_files] }] + end + + it_behaves_like "set_permissions_command: unknown remote identity" + end + + private + + def permission_input_data(file_id, user_permissions) + Storages::Peripherals::StorageInteraction::Inputs::SetPermissions.build(file_id:, user_permissions:).value! + end + + def current_remote_permissions + Storages::Peripherals::StorageInteraction::Authentication[auth_strategy].call(storage:) do |http| + request_url = Storages::UrlBuilder.url(storage.uri, + "remote.php/dav/files", + storage.username, + test_folder.location) + response = http.request(:propfind, request_url, xml: permission_request_body) + parse_acl_xml response.body.to_s + end + end + + def permission_request_body + Nokogiri::XML::Builder.new do |xml| + xml["d"].propfind( + "xmlns:d" => "DAV:", + "xmlns:nc" => "http://nextcloud.org/ns" + ) do + xml["d"].prop do + xml["nc"].send(:"acl-list") + end + end + end.to_xml + end + + def parse_acl_xml(xml) + found_code = "d:status[text() = 'HTTP/1.1 200 OK']" + not_found_code = "d:status[text() = 'HTTP/1.1 404 Not Found']" + happy_path = "/d:multistatus/d:response/d:propstat[#{found_code}]/d:prop/nc:acl-list" + not_found_path = "/d:multistatus/d:response/d:propstat[#{not_found_code}]/d:prop" + + if Nokogiri::XML(xml).xpath(not_found_path).children.map(&:name).include?("acl-list") + [] + else + Nokogiri::XML(xml).xpath(happy_path).children.map do |acl| + acl.children.each_with_object({ user_id: "", permissions: [] }) do |entry, agg| + agg[:user_id] = entry.text if entry.name == "acl-mapping-id" + agg[:permissions] = translate_mask_to_permissions(entry.text.to_i) if entry.name == "acl-permissions" + end + end + end + end + + def translate_mask_to_permissions(number) + described_class::PERMISSIONS_MAP.each_with_object([]) do |(permission, mask), list| + list << permission if number & mask == mask + end + end + + # TODO: Delete folder for nextcloud still works on a location, not a file id. + def clean_up(_file_id) + Storages::Peripherals::Registry + .resolve("nextcloud.commands.delete_folder") + .call(storage:, auth_strategy:, location: test_folder.location) + end +end diff --git a/modules/storages/spec/common/storages/peripherals/storage_interaction/one_drive/set_permissions_command_spec.rb b/modules/storages/spec/common/storages/peripherals/storage_interaction/one_drive/set_permissions_command_spec.rb index b159e49add52..bdf81455e020 100644 --- a/modules/storages/spec/common/storages/peripherals/storage_interaction/one_drive/set_permissions_command_spec.rb +++ b/modules/storages/spec/common/storages/peripherals/storage_interaction/one_drive/set_permissions_command_spec.rb @@ -55,7 +55,7 @@ it_behaves_like "set_permissions_command: basic command setup" - context "if file does not exists", vcr: "one_drive/set_permissions_not_found_folder" do + context "if folder does not exists", vcr: "one_drive/set_permissions_not_found_folder" do let(:error_source) { described_class } let(:input_data) { permission_input_data("THIS_IS_NOT_THE_FOLDER_YOURE_LOOKING_FOR", []) } diff --git a/modules/storages/spec/factories/storage_factory.rb b/modules/storages/spec/factories/storage_factory.rb index 048e890902e7..7922df64a085 100644 --- a/modules/storages/spec/factories/storage_factory.rb +++ b/modules/storages/spec/factories/storage_factory.rb @@ -94,8 +94,8 @@ trait :as_automatically_managed do automatic_management_enabled { true } - username { "OpenProject" } - password { "Password123" } + username { ENV.fetch("NEXTCLOUD_LOCAL_GROUP_USER_NAME", "OpenProject") } + password { ENV.fetch("NEXTCLOUD_LOCAL_GROUP_USER_PASSWORD", "Password123") } end end diff --git a/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_invalid_user_id.yml b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_invalid_user_id.yml new file mode 100644 index 000000000000..8da3f7a241ef --- /dev/null +++ b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_invalid_user_id.yml @@ -0,0 +1,583 @@ +--- +http_interactions: +- request: + method: mkcol + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + response: + status: + code: 201 + message: Created + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - text/html; charset=UTF-8 + Date: + - Fri, 23 Aug 2024 15:28:56 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Oc-Fileid: + - '00000799oc07ul6b4oaw' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=a927f62338c190206dc5985489ac588f; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=bRyCKQt%2BvaqozQGCq5O9nGsdRA3MYge1FOl%2FnoJTqhMCJc5Xtp%2FdIujs5xAgAMBNCJ79BmK0V8vPElc%2BTEuyeW9Dkox1pzuy%2B6XFnp7WA%2BWCW1YnjSvMgcgJ0QC4jAIk; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=a927f62338c190206dc5985489ac588f; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=a927f62338c190206dc5985489ac588f; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=a927f62338c190206dc5985489ac588f; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=afefc644483807ab0a20d724cedf17b8; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:28:56 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - qpmqxAN3kh1MgaA5M9kP + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - qpmqxAN3kh1MgaA5M9kP + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '0' + body: + encoding: UTF-8 + string: '' + recorded_at: Fri, 23 Aug 2024 15:28:56 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + + + + headers: + Authorization: + - Basic + Depth: + - '1' + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '207' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:28:56 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=1d39bc244cb26834517f59232457fc22; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=VkeJavJBnWz4f4x0XDQPffKS8%2BmxaPnSGGnE1gaQSoSQ3zjp%2BnUAopgCI4CZPDFS%2BkPOSulMWsMwskL7gffn3lOWjMmkqmjjcIX8wP9cYH3734TAOB9VVXv%2FxIxKNOi8; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=1d39bc244cb26834517f59232457fc22; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=1d39bc244cb26834517f59232457fc22; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=1d39bc244cb26834517f59232457fc22; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=80adcb3565dc6113f9b26a8e4918e0c9; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:28:57 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - 8CKNsMHvkW8DFaT5EBfj + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 8CKNsMHvkW8DFaT5EBfj + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '317' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/7990Fri, 23 Aug 2024 15:28:56 GMTvcrHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:28:57 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '141' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:28:57 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=3966ed37ff3e0f3cfd19c0efb6d8e5e9; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=TqXez5efLfATpq9veN%2BMj8qIpQJSEjVN1vnSAl7Et4vPL8ZdiQ4e%2BKn3%2FA6qHQ7VQnqBxC%2BMgs6V9hKwGetPRg6BKPcwwAgG457QoJL2NLMxzu88wk%2B%2Fw3iGCkGZI8X9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=3966ed37ff3e0f3cfd19c0efb6d8e5e9; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=3966ed37ff3e0f3cfd19c0efb6d8e5e9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=3966ed37ff3e0f3cfd19c0efb6d8e5e9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5df37f195970f542580d33643b28241f; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:28:57 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - s3I6DIYrwZXkrXQfXTt3 + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - s3I6DIYrwZXkrXQfXTt3 + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '242' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/HTTP/1.1 404 Not Found + recorded_at: Fri, 23 Aug 2024 15:28:57 GMT +- request: + method: get + uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/fileinfo/799 + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + Ocs-Apirequest: + - 'true' + Accept: + - application/json + User-Agent: + - httpx.rb/1.3.0 + Accept-Encoding: + - gzip, deflate + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:28:58 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Feature-Policy: + - autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone + 'none';payment 'none' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=d43f88e2979cf5744aa37e33e9fe808e; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=l7F2I53dDSoDmEwI8u0o5Sc%2FwUSrQytyxOa9CZ3evnKXVI2ADz9KQdj9EcUpmLJCK37lYByr9h0pu9go6O%2FdAbqfzhapvqN6b5mokeTmSw%2BrY0tAj%2Fihc3V5KauWI7l0; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=d43f88e2979cf5744aa37e33e9fe808e; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=d43f88e2979cf5744aa37e33e9fe808e; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=d43f88e2979cf5744aa37e33e9fe808e; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=33cedf5c0faff47baa93a590ad0c7d98; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:28:58 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - xad6qPwHCbI24SjfJp4j + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '261' + body: + encoding: UTF-8 + string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"status":"OK","statuscode":200,"id":799,"name":"Permission + Test Folder","mtime":1724426936,"ctime":0,"mimetype":"application\/x-op-directory","size":0,"owner_name":"vcr","owner_id":"vcr","modifier_name":null,"modifier_id":null,"dav_permissions":"RMGDNVCK","path":"files\/VCR\/Permission + Test Folder\/"}}}' + recorded_at: Fri, 23 Aug 2024 15:28:58 GMT +- request: + method: proppatch + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + user + luke_the_sky + 31 + 31 + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '449' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:28:58 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=f64663a174cf63f891857f7cecdc762c; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=kxiSFoO%2Fr%2FrNvmP7Kqzm3SWiXigcteR7sx6qEntHCj4Zl48lekvxPqDcRyFbqgT1GteQrWX1%2FU9N2f2QRvEFQJKLkYAd2p69N5fnntsM7bhcHy7OfI8OMowg%2F7GZ33tm; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=f64663a174cf63f891857f7cecdc762c; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=f64663a174cf63f891857f7cecdc762c; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=f64663a174cf63f891857f7cecdc762c; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=096557518dff940079c61096954dfdbf; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:28:58 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - zia7mjrTwEB9gk82hKZB + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - zia7mjrTwEB9gk82hKZB + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '361' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20FolderHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:28:58 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '141' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:28:59 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=da2d0fc1963ec3d3360a5e70fa84eca9; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=IyxSuFDWZztk0FR3Z4uOt093IN56tzy7AkgiQvJMaeU%2FLC%2F0SfDzx3whifCPRYRlkND3lGzhHH38Bp2VYUkxYk81FEQcvuZcEnFymAGhtu8Gw75aL2mhvewJJycpCPvA; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=da2d0fc1963ec3d3360a5e70fa84eca9; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=da2d0fc1963ec3d3360a5e70fa84eca9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=da2d0fc1963ec3d3360a5e70fa84eca9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=b7bc2ca49f3404370d1993a9f245d55f; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:28:59 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - qd7FtewIuY0uBLkxF16D + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - qd7FtewIuY0uBLkxF16D + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '237' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/HTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:28:59 GMT +- request: + method: delete + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Date: + - Fri, 23 Aug 2024 15:28:59 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=6c76f9e5a759e63644dcd13d1bc06b06; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=4oZSLGHq7iAinHIJWgDLoZNxlzts1Pucs35gdK8l%2FWnr9TvIRVrhg35w4UOCvP%2BVSVd6neLVQdU3fm%2FUSi%2FBhcDr2eKruTWxY%2BABX%2B1eGSKDrhFmuoY0EjDRGNRM96YI; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=6c76f9e5a759e63644dcd13d1bc06b06; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=6c76f9e5a759e63644dcd13d1bc06b06; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=6c76f9e5a759e63644dcd13d1bc06b06; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=ce46076e65d4e4ac29941b7014d77127; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:29:00 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - 4okZgkeMXq77RY0tGOdX + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 4okZgkeMXq77RY0tGOdX + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '' + recorded_at: Fri, 23 Aug 2024 15:29:00 GMT +recorded_with: VCR 6.3.1 diff --git a/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_new.yml b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_new.yml new file mode 100644 index 000000000000..f1cb0ba11a47 --- /dev/null +++ b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_new.yml @@ -0,0 +1,589 @@ +--- +http_interactions: +- request: + method: mkcol + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + response: + status: + code: 201 + message: Created + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - text/html; charset=UTF-8 + Date: + - Fri, 23 Aug 2024 15:24:06 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Oc-Fileid: + - '00000797oc07ul6b4oaw' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=74b176b39999321593cdb46fe93a1ab7; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=8OBhmDZnsGKvpQwTKnu3S98mkjwAAo4jTDbwXB8hP3R6tqTLZzBXI8vnTLh2f2U0KL9Wfcd9wYnc79QeTZqbenUXkazphMN1NZmHEnAe%2ForMjauG3UpJj6ZjsMY%2BysRI; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=74b176b39999321593cdb46fe93a1ab7; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=74b176b39999321593cdb46fe93a1ab7; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=74b176b39999321593cdb46fe93a1ab7; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=42eabe3621d5f85ca224a1b337b5aec9; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:06 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - gxLitMLErAVUKSLxgaR4 + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - gxLitMLErAVUKSLxgaR4 + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '0' + body: + encoding: UTF-8 + string: '' + recorded_at: Fri, 23 Aug 2024 15:24:06 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + + + + headers: + Authorization: + - Basic + Depth: + - '1' + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '207' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:24:06 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=5c73dd535d041be35b60683308dc51b0; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=R6PHecef0iz1z6vQvhNYGs3kbomaUz10sryqnAmX6ZsbyGOmt35pIvr7q7skxzf6YZs4Em6SdmRilO6CoY72UCGQM5EuWPHfMRerJ1%2FBt0fS75QYqFhee7b6FRCWXfqg; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5c73dd535d041be35b60683308dc51b0; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=5c73dd535d041be35b60683308dc51b0; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5c73dd535d041be35b60683308dc51b0; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=bf2eedf5e9cb535e292d356d7edbbc31; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:07 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - PdF2WKadP5qYbIbgwpna + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - PdF2WKadP5qYbIbgwpna + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '316' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/7970Fri, 23 Aug 2024 15:24:06 GMTvcrHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:24:07 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '141' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:24:07 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=b4c42d807cf6c7f75a45e7b12a82cf86; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=SbwSJTxaDMzz4eg%2F3ox%2FWb1s8Bt5l2ZFaCmMcakuW4Sm0DE%2FpZr%2FBYJ8X9bWtM1%2B0ZVBswv2wB1SQLILciDAokNfRL2aLbOQjUbcKrTv9dv301Ujx8ApreNP8XQ73%2FNg; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=b4c42d807cf6c7f75a45e7b12a82cf86; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=b4c42d807cf6c7f75a45e7b12a82cf86; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=b4c42d807cf6c7f75a45e7b12a82cf86; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=7d0e57ac281d9fa686cc283083170a02; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:07 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - P0vKEAM4rlqxi5KErKT2 + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - P0vKEAM4rlqxi5KErKT2 + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '242' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/HTTP/1.1 404 Not Found + recorded_at: Fri, 23 Aug 2024 15:24:07 GMT +- request: + method: get + uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/fileinfo/797 + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + Ocs-Apirequest: + - 'true' + Accept: + - application/json + User-Agent: + - httpx.rb/1.3.0 + Accept-Encoding: + - gzip, deflate + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:24:08 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Feature-Policy: + - autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone + 'none';payment 'none' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=fc292c6fb77bc80750da2843fb90378d; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=g3S3TQIkXz8o7U5WMqvkpIUNs28DzalQJox4XKLUhPPbQZYlSbS4tHAjM7KeDJJNgw8K5GsNeEiTq7l87Js16%2BFnOy8%2BNOrk1biGvK50zR6gKiIZgZIwa1XN7G237r47; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=fc292c6fb77bc80750da2843fb90378d; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=fc292c6fb77bc80750da2843fb90378d; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=fc292c6fb77bc80750da2843fb90378d; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5037847659aef38cb75a7eaa7bc3840f; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:08 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 9tiQdU7th3tUXAYNB240 + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '261' + body: + encoding: UTF-8 + string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"status":"OK","statuscode":200,"id":797,"name":"Permission + Test Folder","mtime":1724426646,"ctime":0,"mimetype":"application\/x-op-directory","size":0,"owner_name":"vcr","owner_id":"vcr","modifier_name":null,"modifier_id":null,"dav_permissions":"RMGDNVCK","path":"files\/VCR\/Permission + Test Folder\/"}}}' + recorded_at: Fri, 23 Aug 2024 15:24:08 GMT +- request: + method: proppatch + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + user + m.jade@death.star + 31 + 3 + + + user + admin + 31 + 15 + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '695' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:24:08 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=c99c90a58dec00489d188ab5ef3cee41; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=43WfCS9%2BycATIK%2BWfNV1V9LvsHDRd8ogMmfESfm0H9cZg8FiKMaaVPs%2BuRiLR0RhMwLq%2B9f5lbYWNga30l%2Fm5WljE%2FZ4S6mRlLvYRtIHJhzX7pXGHQgfrGRyG8bGDJAd; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=c99c90a58dec00489d188ab5ef3cee41; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=c99c90a58dec00489d188ab5ef3cee41; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=c99c90a58dec00489d188ab5ef3cee41; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=87863e4c9edc278c917fbfdc50cb859d; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:09 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - HRC46zIFqGq9lqyTaKLq + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - HRC46zIFqGq9lqyTaKLq + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '361' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20FolderHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:24:09 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '141' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:24:09 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=83b8c19174d62898c93cb76ac2aeb129; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=erl2KC3rO7N%2BJhYpvoIoNFaQPWs9%2FOkiqOSvL%2Bssc8mft38qNcXfCKtdvhfgKTJiKXwM9wvrYz%2BlC3WIOtWV5%2FihLtea6S6aQewYMgNgTGdjuB%2FLk9Mhu8IhGHZmIl9N; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=83b8c19174d62898c93cb76ac2aeb129; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=83b8c19174d62898c93cb76ac2aeb129; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=83b8c19174d62898c93cb76ac2aeb129; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=4bdc08280204d6382d359d97b1d6774e; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:09 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - mLH7DEGThVPycAIFKroF + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - mLH7DEGThVPycAIFKroF + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '344' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/userm.jade@death.starMara Jade313useradminadmin3115HTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:24:09 GMT +- request: + method: delete + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Date: + - Fri, 23 Aug 2024 15:24:09 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=df8ba7197fee1bd3c22d8cb5d4da5f0f; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=DKKB2DVEfvjfESplibbCXGSATJgbBuIljXzN0HO7g1sph7Bha%2B4eLbax8GSmeCncbA27kGjlae9gimPArVraSfk%2BmTHZZvB%2BadYhjSqGsa6bwfLbpFSNKkLveczOAuDX; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=df8ba7197fee1bd3c22d8cb5d4da5f0f; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=df8ba7197fee1bd3c22d8cb5d4da5f0f; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=df8ba7197fee1bd3c22d8cb5d4da5f0f; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5c8726bc48c7d7c1a14b813840d73df7; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:24:10 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - G8MAfZQcMdxpEya9IKDm + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - G8MAfZQcMdxpEya9IKDm + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '' + recorded_at: Fri, 23 Aug 2024 15:24:10 GMT +recorded_with: VCR 6.3.1 diff --git a/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_not_found_folder.yml b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_not_found_folder.yml new file mode 100644 index 000000000000..a2b5212ea582 --- /dev/null +++ b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_not_found_folder.yml @@ -0,0 +1,82 @@ +--- +http_interactions: +- request: + method: get + uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/fileinfo/1337 + body: + encoding: US-ASCII + string: '' + headers: + Ocs-Apirequest: + - 'true' + Accept: + - application/json + Authorization: + - Bearer + User-Agent: + - httpx.rb/1.3.0 + Accept-Encoding: + - gzip, deflate + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 22 Aug 2024 13:57:21 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Feature-Policy: + - autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone + 'none';payment 'none' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=%2FHlV8RIDNjpe8JA3B1xRL9D4KJjPxF58URV3%2BSDrVF3NyRfBaqkNhybyvQsTnjK5IW5EMqdFAudwlsn12XwX45Jl1fc46dUblvpiAPhyHHpHr0hRstZcuh5nhbxjnFL5; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=35ca0a83fcacc147c7ca115af59be368; + path=/; secure; HttpOnly; SameSite=Lax + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - yvczEEmwKCNz0CSjXbKZ + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '115' + body: + encoding: UTF-8 + string: '{"ocs":{"meta":{"status":"failure","statuscode":404,"message":"","totalitems":"","itemsperpage":""},"data":{"status":"Not + Found","statuscode":404}}}' + recorded_at: Thu, 22 Aug 2024 13:57:21 GMT +recorded_with: VCR 6.3.1 diff --git a/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_replacing_permissions.yml b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_replacing_permissions.yml new file mode 100644 index 000000000000..f4f6b2382043 --- /dev/null +++ b/modules/storages/spec/support/fixtures/vcr_cassettes/nextcloud/set_permissions_replacing_permissions.yml @@ -0,0 +1,753 @@ +--- +http_interactions: +- request: + method: mkcol + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + response: + status: + code: 201 + message: Created + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - text/html; charset=UTF-8 + Date: + - Fri, 23 Aug 2024 15:26:33 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Oc-Fileid: + - '00000798oc07ul6b4oaw' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=4bdc955e4c45bfb489b7c6c6a8238af9; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=fULfFr9AnKFX8irP01I5BrbS1YksG23yjO3qhg9yszZA6XWAx1rlbETLIMNowhJULhPE%2BjyUleLAk4Y4q6XULT1mKf%2F3tHG8YkWvaHJbxZVN5StcfoBe0OYyxcf90Nrf; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=4bdc955e4c45bfb489b7c6c6a8238af9; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=4bdc955e4c45bfb489b7c6c6a8238af9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=4bdc955e4c45bfb489b7c6c6a8238af9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=7b6e76611b4ea143af914303426f98a0; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:33 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - d2Ro8iV9SHAOEB37vcy7 + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - d2Ro8iV9SHAOEB37vcy7 + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '0' + body: + encoding: UTF-8 + string: '' + recorded_at: Fri, 23 Aug 2024 15:26:33 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + + + + headers: + Authorization: + - Basic + Depth: + - '1' + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '207' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:33 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=828a5403f8b9b5d4234d61ffd4028a51; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=x2ZFPW1QB9Wly7wMZLypJbghpPWU%2B6bk3fXEadX0RNkc9qlBN1tdZAhIqJN2pCCOrajysHjPKcp7m%2FYBp4OwANLNEg%2Fluvq1puD5LCSN5mUBSWf3g9fv8MsUY2clAfAq; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=828a5403f8b9b5d4234d61ffd4028a51; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=828a5403f8b9b5d4234d61ffd4028a51; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=828a5403f8b9b5d4234d61ffd4028a51; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=ad7e5549db3469570c7cef3f307afdd7; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:34 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - QY2rFOq3Xd4NgNCeMQ5w + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - QY2rFOq3Xd4NgNCeMQ5w + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '316' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/7980Fri, 23 Aug 2024 15:26:33 GMTvcrHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:26:34 GMT +- request: + method: get + uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/fileinfo/798 + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + Ocs-Apirequest: + - 'true' + Accept: + - application/json + User-Agent: + - httpx.rb/1.3.0 + Accept-Encoding: + - gzip, deflate + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:34 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Feature-Policy: + - autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone + 'none';payment 'none' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=ca139155711a124dbbab76f6ef3d8782; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=2kO7yTFilkF07qvq3qTJV%2BJM823VMmXy17yn7y3gYyO7fqXfQszyfMVgeNO27cPD9olAUjV0ID0W4OhdDMM5dLDz93VwSHISNHH%2BAiqKnIKdYn0pxwwSSilhjf%2BHypQc; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=ca139155711a124dbbab76f6ef3d8782; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=ca139155711a124dbbab76f6ef3d8782; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=ca139155711a124dbbab76f6ef3d8782; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=aa22a60f880597736d1ca317124abd1d; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:34 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - WClWp45DMBDLQ6XconNr + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '261' + body: + encoding: UTF-8 + string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"status":"OK","statuscode":200,"id":798,"name":"Permission + Test Folder","mtime":1724426793,"ctime":0,"mimetype":"application\/x-op-directory","size":0,"owner_name":"vcr","owner_id":"vcr","modifier_name":null,"modifier_id":null,"dav_permissions":"RMGDNVCK","path":"files\/VCR\/Permission + Test Folder\/"}}}' + recorded_at: Fri, 23 Aug 2024 15:26:34 GMT +- request: + method: proppatch + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + user + admin + 31 + 15 + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '442' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:34 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=e2e120d0dbe5cdec92afa2a123bdd9d9; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=lCZK%2BWqP%2F3gfto7vQL6maRU%2FUFEyKlUm67%2BQaJ5vwY1gkY9BKeU5bPeHHQjsxYpfIEHxyFcg6mZZStOUd71YYCstbAxqkSuZXDm7qSnX1nLN5NM37ijudNhMskJ1vwoZ; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=e2e120d0dbe5cdec92afa2a123bdd9d9; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=e2e120d0dbe5cdec92afa2a123bdd9d9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=e2e120d0dbe5cdec92afa2a123bdd9d9; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=ae983ee287222375c3b74e349612cd32; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:35 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - epFCyG538uE4TjdpMs0r + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - epFCyG538uE4TjdpMs0r + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '361' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20FolderHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:26:35 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '141' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:35 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=877eeca28064e7c6a6eaee885102e2ab; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=fNBRyW9Ml74UeyACErBwVJD1u%2BoZzGKm8syfmNqrcGb2IQ4YnXDyZMfJMx4uFTI3mt4mXkWCHmjjQ76EhSZxQTi3tj7trFwHvmWnfZnODNxTIiWoPMhByEdJzR5CSCKE; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=877eeca28064e7c6a6eaee885102e2ab; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=877eeca28064e7c6a6eaee885102e2ab; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=877eeca28064e7c6a6eaee885102e2ab; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5801f0074f37e8124555affc9f8164a9; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:35 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - 6R18cmvTStT5GzEHzgBv + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 6R18cmvTStT5GzEHzgBv + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '308' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/useradminadmin3115HTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:26:35 GMT +- request: + method: get + uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/fileinfo/798 + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + Ocs-Apirequest: + - 'true' + Accept: + - application/json + User-Agent: + - httpx.rb/1.3.0 + Accept-Encoding: + - gzip, deflate + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none' + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:35 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Feature-Policy: + - autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone + 'none';payment 'none' + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=e1621dc4839a418a3da3b7482f4a4af4; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=e8EdRubABsLZSLVT15N0oi4RPL1pInsn3J1J1I3bG6niFmDglQgyLl%2FXHMTl4maA6CHOBmCA6HkLJdGFealwM%2Bafg9C97NYNx4CDefroo3gTT6iE8PfC%2FCk1D%2Bf03AX%2B; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=e1621dc4839a418a3da3b7482f4a4af4; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=e1621dc4839a418a3da3b7482f4a4af4; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=e1621dc4839a418a3da3b7482f4a4af4; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=27b832bfca74cd82d7aba2a5cc831a74; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:36 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 1MElYQLofrVumUuexucB + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '261' + body: + encoding: UTF-8 + string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"status":"OK","statuscode":200,"id":798,"name":"Permission + Test Folder","mtime":1724426793,"ctime":0,"mimetype":"application\/x-op-directory","size":0,"owner_name":"vcr","owner_id":"vcr","modifier_name":null,"modifier_id":null,"dav_permissions":"RMGDNVCK","path":"files\/VCR\/Permission + Test Folder\/"}}}' + recorded_at: Fri, 23 Aug 2024 15:26:36 GMT +- request: + method: proppatch + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + user + m.jade@death.star + 31 + 3 + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '453' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:36 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=998aa8e8349469e6025630b4ab7bd91b; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=o4FtzrnG5FA8fm1B2342KKh6zQ7whCp7y5%2FsPFGteKcL01ApoZsd49nCpzlq16gsI9J80RRspEy4SgxklUXopo6Vg6g6FQOE20jK3kVHw6vgMKH4nln%2BuegQcoLmFCti; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=998aa8e8349469e6025630b4ab7bd91b; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=998aa8e8349469e6025630b4ab7bd91b; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=998aa8e8349469e6025630b4ab7bd91b; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=44e4acfdb3693d7a001e982efed6634b; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:36 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - 7upsO7ftiIwKoTthQuUo + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 7upsO7ftiIwKoTthQuUo + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '361' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20FolderHTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:26:36 GMT +- request: + method: propfind + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: UTF-8 + string: | + + + + + + + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + Content-Type: + - application/xml; charset=utf-8 + Content-Length: + - '141' + response: + status: + code: 207 + message: Multi-Status + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Encoding: + - gzip + Content-Security-Policy: + - default-src 'none'; + Content-Type: + - application/xml; charset=utf-8 + Date: + - Fri, 23 Aug 2024 15:26:36 GMT + Dav: + - 1, 3, extended-mkcol, access-control, calendarserver-principal-property-search, + nextcloud-checksum-update, nc-calendar-search, nc-enable-birthday-calendar + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=52d69c1d7a7fe7eaf8d6ca52ab2f4a07; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=AqEZt%2BCZtSb0DfV9DWV%2BATHJMv4yxI5V5D0tjpb4xo5y6yTOVdPOSfxPy%2B4z7hhFNWkKaE2BsaJyg7pZaPwrIDuoI0I8t9zQx1StRAMIGi1fZ2ehFyxy6p5aXYU89adP; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=52d69c1d7a7fe7eaf8d6ca52ab2f4a07; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=52d69c1d7a7fe7eaf8d6ca52ab2f4a07; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=52d69c1d7a7fe7eaf8d6ca52ab2f4a07; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=a192ddb5cc0fd28366a3817e63918c03; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:37 GMT; Max-Age=3600 + Vary: + - Brief,Prefer + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - Vm3bHPGdkJLTBdwxMjGA + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - Vm3bHPGdkJLTBdwxMjGA + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '323' + body: + encoding: UTF-8 + string: | + + /remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder/userm.jade@death.starMara Jade313HTTP/1.1 200 OK + recorded_at: Fri, 23 Aug 2024 15:26:37 GMT +- request: + method: delete + uri: https://nextcloud.local/remote.php/dav/files/vcr/VCR/Permission%20Test%20Folder + body: + encoding: US-ASCII + string: '' + headers: + Authorization: + - Basic + User-Agent: + - httpx.rb/1.3.0 + Accept: + - "*/*" + Accept-Encoding: + - gzip, deflate + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-store, no-cache, must-revalidate + Content-Security-Policy: + - default-src 'none'; + Date: + - Fri, 23 Aug 2024 15:26:37 GMT + Expires: + - Thu, 19 Nov 1981 08:52:00 GMT + Pragma: + - no-cache + Referrer-Policy: + - no-referrer + Server: + - Apache/2.4.59 (Debian) + Set-Cookie: + - oc07ul6b4oaw=d34aa616c0c48ff9dbb536e8b80fd648; path=/; secure; HttpOnly; SameSite=Lax, + oc_sessionPassphrase=bmQJTIglM4KMdcaqKejNIGOz9M%2BTvm91oG%2FNR8MUhe6kzaAbO%2FoigUHR78Sjro%2BfCV43F8KKnYOR944ankZZ4VOQoR3uwzcCfyO7zYys%2B4OFcIqFE4foZW6yIyogP2LM; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=d34aa616c0c48ff9dbb536e8b80fd648; + path=/; secure; HttpOnly; SameSite=Lax, __Host-nc_sameSiteCookielax=true; + path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax, + __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, + 31-Dec-2100 23:59:59 GMT; SameSite=strict, oc07ul6b4oaw=d34aa616c0c48ff9dbb536e8b80fd648; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=d34aa616c0c48ff9dbb536e8b80fd648; + path=/; secure; HttpOnly; SameSite=Lax, oc07ul6b4oaw=5c7e759e733203278a6d58494ecd1ded; + path=/; secure; HttpOnly; SameSite=Lax, cookie_test=test; expires=Fri, 23 + Aug 2024 16:26:37 GMT; Max-Age=3600 + X-Content-Type-Options: + - nosniff + X-Debug-Token: + - 42Fbkghfgc58fjOlgVs3 + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Powered-By: + - PHP/8.2.21 + X-Request-Id: + - 42Fbkghfgc58fjOlgVs3 + X-Robots-Tag: + - noindex, nofollow + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '' + recorded_at: Fri, 23 Aug 2024 15:26:37 GMT +recorded_with: VCR 6.3.1 diff --git a/modules/storages/spec/support/shared_examples_for_adapters/set_permissions_command_examples.rb b/modules/storages/spec/support/shared_examples_for_adapters/set_permissions_command_examples.rb index bf9659503b2f..d6e7926d906d 100644 --- a/modules/storages/spec/support/shared_examples_for_adapters/set_permissions_command_examples.rb +++ b/modules/storages/spec/support/shared_examples_for_adapters/set_permissions_command_examples.rb @@ -86,6 +86,24 @@ end end +RSpec.shared_examples_for "set_permissions_command: unknown remote identity" do + it "returns a failure" do + file_id = test_folder.id + input_data = Storages::Peripherals::StorageInteraction::Inputs::SetPermissions + .build(file_id:, user_permissions:) + .value! + result = described_class.call(storage:, auth_strategy:, input_data:) + + expect(result).to be_failure + + error = result.errors + expect(error.code).to eq(:unknown_remote_identity) + expect(error.data.source).to eq(error_source) + ensure + clean_up file_id + end +end + RSpec.shared_examples_for "set_permissions_command: not found" do it "returns a failure" do result = described_class.call(storage:, auth_strategy:, input_data:) From 86bb5018c3c32dbb1c8efb59b561001589dc223f Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Thu, 29 Aug 2024 09:35:09 +0200 Subject: [PATCH 3/5] [#57286] fixed test preparation for CI --- .../nextcloud/set_permissions_command_spec.rb | 2 +- modules/storages/spec/factories/storage_factory.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb b/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb index 6fd0509d7f1e..0f5e7ef7b2be 100644 --- a/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb +++ b/modules/storages/spec/common/storages/peripherals/storage_interaction/nextcloud/set_permissions_command_spec.rb @@ -33,7 +33,7 @@ RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::SetPermissionsCommand, :webmock do let(:user) { create(:user) } - let(:storage) { create(:nextcloud_storage_with_local_connection, :as_automatically_managed) } + let(:storage) { create(:nextcloud_storage_with_local_connection, :as_automatically_managed, username: "vcr") } let(:auth_strategy) { Storages::Peripherals::Registry.resolve("nextcloud.authentication.userless").call } let(:test_folder) do diff --git a/modules/storages/spec/factories/storage_factory.rb b/modules/storages/spec/factories/storage_factory.rb index 7922df64a085..f31ed752dd2b 100644 --- a/modules/storages/spec/factories/storage_factory.rb +++ b/modules/storages/spec/factories/storage_factory.rb @@ -94,7 +94,7 @@ trait :as_automatically_managed do automatic_management_enabled { true } - username { ENV.fetch("NEXTCLOUD_LOCAL_GROUP_USER_NAME", "OpenProject") } + username { "OpenProject" } password { ENV.fetch("NEXTCLOUD_LOCAL_GROUP_USER_PASSWORD", "Password123") } end end From 0795a710690891882a57a0d6a42b66f87b886068 Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Wed, 4 Sep 2024 13:59:51 +0200 Subject: [PATCH 4/5] [#57286] fixed test preparation after rebase - rebase contained rework of nextcloud sync service --- .../nextcloud_managed_folder_sync_service.rb | 6 +- ...tcloud_managed_folder_sync_service_spec.rb | 123 ++++++++++++------ 2 files changed, 89 insertions(+), 40 deletions(-) diff --git a/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb b/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb index 934a2ea1a4e0..7e11442ec13e 100644 --- a/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb +++ b/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb @@ -136,7 +136,9 @@ def set_folder_permissions(remote_admins, project_storage) { user_id: identity.origin_user_id, permissions: } end - permissions = system_user + admin_permissions + users_permissions + group_permissions = [{ group_id: @storage.group, permissions: [] }] + + permissions = system_user + admin_permissions + users_permissions + group_permissions project_folder_id = project_storage.project_folder_id build_set_permissions_input_data(project_folder_id, permissions) @@ -156,7 +158,7 @@ def set_folder_permissions(remote_admins, project_storage) def project_remote_identities(project_storage) remote_identities = remote_identities_scope.where.not(id: admin_remote_identities_scope).order(:id) - if project_storage.project.public? && ProjectRole.non_member.permissions.intersect?(PERMISSIONS_KEYS) + if project_storage.project.public? && ProjectRole.non_member.permissions.intersect?(FILE_PERMISSIONS) remote_identities else remote_identities.where(user: project_storage.project.users) diff --git a/modules/storages/spec/services/storages/nextcloud_managed_folder_sync_service_spec.rb b/modules/storages/spec/services/storages/nextcloud_managed_folder_sync_service_spec.rb index 471b3ce3131a..68f90093dcb2 100644 --- a/modules/storages/spec/services/storages/nextcloud_managed_folder_sync_service_spec.rb +++ b/modules/storages/spec/services/storages/nextcloud_managed_folder_sync_service_spec.rb @@ -98,10 +98,14 @@ module Storages let(:remove_user) { class_double(Peripherals::StorageInteraction::Nextcloud::RemoveUserFromGroupCommand) } let(:auth_strategy) { Peripherals::StorageInteraction::AuthenticationStrategies::Strategy.new(key: :basic_auth) } + let(:root_folder_id) { "root_folder_id" } let(:file_ids_result) do ServiceResult.success( - result: { inactive_storage.managed_project_folder_path => { "fileid" => "12345" }, - "/OpenProject/Another Name for this Project" => { "fileid" => "9001" } } + result: { + "/OpenProject/" => { "fileid" => root_folder_id }, + inactive_storage.managed_project_folder_path => { "fileid" => inactive_storage.project_folder_id }, + "/OpenProject/Another Name for this Project/" => { "fileid" => renamed_storage.project_folder_id } + } ) end @@ -109,10 +113,18 @@ module Storages ServiceResult.success(result: %w[OpenProject admin multiple_projects_user cookiemonster]) end - let(:group_permissions_result) { ServiceResult.success } - let(:group_permissions) { { groups: { OpenProject: 1 }, users: { OpenProject: 31 } } } + let(:root_permissions_result) { ServiceResult.success } + let(:root_permission_input) do + build_input_data( + "root_folder_id", + [ + { user_id: "OpenProject", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { group_id: "OpenProject", permissions: %i[read_files] } + ] + ) + end - let(:projects_folder_permissions) { build_project_folder_permissions } + let(:projects_folder_permissions) { build_project_folder_permission_input } let(:rename_file_result) do StorageFile.new(id: renamed_storage.project_folder_id, name: renamed_storage.managed_project_folder_name, @@ -138,9 +150,8 @@ module Storages # We arent using ParentFolder nor AuthStrategies on FileIds allow(file_ids).to receive(:call).with(storage:, path: storage.group).and_return(file_ids_result) # Setting the Group Permissions - allow(set_permissions) - .to receive(:call).with(storage:, auth_strategy:, path: storage.group, - permissions: group_permissions).and_return(group_permissions_result) + allow(set_permissions).to receive(:call).with(storage:, auth_strategy:, input_data: root_permission_input) + .and_return(root_permissions_result) # Creating folders allow(create_folder).to receive(:call).with(storage:, auth_strategy:, parent_location:, @@ -157,8 +168,8 @@ module Storages .and_return(ServiceResult.success(result: rename_file_result)) # Project Permissions + Hiding Projects - projects_folder_permissions.each_pair do |path, permissions| - allow(set_permissions).to receive(:call).with(storage:, auth_strategy:, path:, permissions:) + projects_folder_permissions.each do |input_data| + allow(set_permissions).to receive(:call).with(storage:, auth_strategy:, input_data:) .and_return(ServiceResult.success) end @@ -181,7 +192,12 @@ module Storages context "when a project is renamed" do let(:file_ids_result) do - ServiceResult.success(result: { "OBVIOUSLY NON RENAMED" => { "fileid" => renamed_storage.project_folder_id } }) + ServiceResult.success( + result: { + "/OpenProject/" => { "fileid" => root_folder_id }, + "/OpenProject/OBVIOUSLY NON RENAMED/" => { "fileid" => renamed_storage.project_folder_id } + } + ) end let(:group_users_result) do @@ -193,7 +209,9 @@ module Storages it "requests to rename the folder to the new managed folder name" do service.call(storage) expect(rename_file).to have_received(:call) - .with(storage:, auth_strategy:, file_id: renamed_storage.project_folder_id, + .with(storage:, + auth_strategy:, + file_id: renamed_storage.project_folder_id, name: renamed_storage.managed_project_folder_name).once end @@ -203,19 +221,15 @@ module Storages end context "with a public project" do - let(:file_ids_result) { ServiceResult.success(result: {}) } - - let(:permissions) do - { groups: { OpenProject: 0 }, - users: { "OpenProject" => 31, "admin" => 31, "single_project_user" => 1, "multiple_projects_user" => 1 } } - end + let(:file_ids_result) { ServiceResult.success(result: { "/OpenProject/" => { "fileid" => root_folder_id } }) } before { ProjectStorage.where.not(id: public_storage.id).delete_all } it "allows sets permissions to all signed-in users" do + input_data = build_project_folder_permission_input[1] # The permissions for the public project + service.call(storage) - expect(set_permissions).to have_received(:call).with(storage:, auth_strategy:, permissions:, - path: public_storage.managed_project_folder_path).once + expect(set_permissions).to have_received(:call).with(storage:, auth_strategy:, input_data:).once end end @@ -235,11 +249,10 @@ module Storages context "with an archived project" do it "hides the project folder" do - perms = build_project_folder_permissions[inactive_storage.managed_project_folder_path] + input_data = build_project_folder_permission_input[0] service.call(storage) - expect(set_permissions).to have_received(:call).with(storage:, auth_strategy:, permissions: perms, - path: inactive_storage.managed_project_folder_path).once + expect(set_permissions).to have_received(:call).with(storage:, auth_strategy:, input_data:).once end end @@ -276,7 +289,7 @@ module Storages end context "when we fail to set the root folder permissions" do - let(:group_permissions_result) do + let(:root_permissions_result) do errors = storage_error(:error, "error body", Peripherals::StorageInteraction::Nextcloud::SetPermissionsCommand) ServiceResult.failure(result: :unauthorized, errors:) end @@ -286,7 +299,11 @@ module Storages service.call(storage) expect(Rails.logger).to have_received(:error) - .with(error_code: :error, message: "TESTING", folder: "OpenProject", data: "error body") + .with(error_code: :error, + message: "TESTING", + folder: "root", + data: "error body", + root_folder_id: "root_folder_id") end it "adds to the services errors" do @@ -357,19 +374,49 @@ def build_create_folder_result } end - def build_project_folder_permissions - { - inactive_storage.managed_project_folder_path => { groups: { OpenProject: 0 }, users: { OpenProject: 31 } }, - public_storage.managed_project_folder_path => { groups: { OpenProject: 0 }, - users: { "OpenProject" => 31, "admin" => 31, "single_project_user" => 1, - "multiple_projects_user" => 1 } }, - project_storage.managed_project_folder_path => { groups: { OpenProject: 0 }, - users: { "OpenProject" => 31, "admin" => 31, - "multiple_projects_user" => 3, "single_project_user" => 3 } }, - renamed_storage.managed_project_folder_path => { groups: { OpenProject: 0 }, - users: { "OpenProject" => 31, "admin" => 31, - "multiple_projects_user" => 3 } } - } + def build_project_folder_permission_input + [ + build_input_data( + inactive_storage.project_folder_id, + [ + { user_id: "OpenProject", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { group_id: "OpenProject", permissions: [] } + ] + ), + build_input_data( + "public_id", + [ + { user_id: "OpenProject", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { user_id: "admin", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { user_id: "multiple_projects_user", permissions: %i[read_files] }, + { user_id: "single_project_user", permissions: %i[read_files] }, + { group_id: "OpenProject", permissions: [] } + ] + ), + build_input_data( + "normal_project_id", + [ + { user_id: "OpenProject", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { user_id: "admin", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { user_id: "multiple_projects_user", permissions: %i[read_files write_files] }, + { user_id: "single_project_user", permissions: %i[read_files write_files] }, + { group_id: "OpenProject", permissions: [] } + ] + ), + build_input_data( + renamed_storage.project_folder_id, + [ + { user_id: "OpenProject", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { user_id: "admin", permissions: OpenProject::Storages::Engine.external_file_permissions }, + { user_id: "multiple_projects_user", permissions: %i[read_files write_files] }, + { group_id: "OpenProject", permissions: [] } + ] + ) + ] + end + + def build_input_data(file_id, user_permissions) + Peripherals::StorageInteraction::Inputs::SetPermissions.build(file_id:, user_permissions:).value! end end end From ba565a77d50a7a1d1ac588fda0dd235721bfd0a9 Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Thu, 5 Sep 2024 11:17:18 +0200 Subject: [PATCH 5/5] [#57286] replace either with value_or --- .../nextcloud_managed_folder_sync_service.rb | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb b/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb index 7e11442ec13e..0bd046524fde 100644 --- a/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb +++ b/modules/storages/app/services/storages/nextcloud_managed_folder_sync_service.rb @@ -141,16 +141,15 @@ def set_folder_permissions(remote_admins, project_storage) permissions = system_user + admin_permissions + users_permissions + group_permissions project_folder_id = project_storage.project_folder_id - build_set_permissions_input_data(project_folder_id, permissions) - .either( - ->(input_data) do - set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| - log_storage_error(service_result.errors, folder: project_folder_id) - add_error(:set_folder_permission, service_result.errors, options: { folder: project_folder_id }) - end - end, - ->(failure) { log_validation_error(failure, project_folder_id:, permissions:) } - ) + input_data = build_set_permissions_input_data(project_folder_id, permissions).value_or do |failure| + log_validation_error(failure, project_folder_id:, permissions:) + return # rubocop:disable Lint/NonLocalExitFromIterator + end + + set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| + log_storage_error(service_result.errors, folder: project_folder_id) + add_error(:set_folder_permission, service_result.errors, options: { folder: project_folder_id }) + end end # rubocop:enable Metrics/AbcSize @@ -181,16 +180,15 @@ def hide_inactive_folders(remote_folders) { group_id: @storage.group, permissions: [] } ] - build_set_permissions_input_data(folder_id, permissions) - .either( - ->(input_data) do - set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| - log_storage_error(service_result.errors, folder_id:, context: "hide_folder") - add_error(:hide_inactive_folders, service_result.errors, options: { folder_id: }) - end - end, - ->(failure) { log_validation_error(failure, folder_id:, permissions:) } - ) + input_data = build_set_permissions_input_data(folder_id, permissions).value_or do |failure| + log_validation_error(failure, folder_id:, permissions:) + return # rubocop:disable Lint/NonLocalExitFromIterator + end + + set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| + log_storage_error(service_result.errors, folder_id:, context: "hide_folder") + add_error(:hide_inactive_folders, service_result.errors, options: { folder_id: }) + end end end @@ -270,19 +268,15 @@ def ensure_root_folder_permissions(root_folder_id) { group_id: group, permissions: [:read_files] } ] - build_set_permissions_input_data(root_folder_id, permissions) - .either( - ->(input_data) do - set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| - log_storage_error(service_result.errors, folder: "root", root_folder_id:) - add_error(:ensure_root_folder_permissions, service_result.errors, options: { group:, username: }).fail! - end - end, - ->(failure) do - log_validation_error(failure, root_folder_id:, permissions:) - ServiceResult.failure(result: failure.errors.to_h) # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods - end - ) + input_data = build_set_permissions_input_data(root_folder_id, permissions).value_or do |failure| + log_validation_error(failure, root_folder_id:, permissions:) + return ServiceResult.failure(result: failure.errors.to_h) # rubocop:disable Rails/DeprecatedActiveModelErrorsMethods + end + + set_permissions.call(storage: @storage, auth_strategy:, input_data:).on_failure do |service_result| + log_storage_error(service_result.errors, folder: "root", root_folder_id:) + add_error(:ensure_root_folder_permissions, service_result.errors, options: { group:, username: }).fail! + end end # rubocop:enable Metrics/AbcSize