Skip to content

Commit

Permalink
Merge pull request #16673 from opf/implementation/57708-use-authentic…
Browse files Browse the repository at this point in the history
…ation-in-file_ids_query

[#57708] removed file ids query
  • Loading branch information
Kharonus authored Sep 10, 2024
2 parents 8001769 + 92277f6 commit d63c814
Show file tree
Hide file tree
Showing 15 changed files with 497 additions and 389 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ module Peripherals
register(:auth_check, StorageInteraction::Nextcloud::AuthCheckQuery)
register(:capabilities, StorageInteraction::Nextcloud::CapabilitiesQuery)
register(:download_link, StorageInteraction::Nextcloud::DownloadLinkQuery)
register(:file_ids, StorageInteraction::Nextcloud::FileIdsQuery)
register(:file_info, StorageInteraction::Nextcloud::FileInfoQuery)
register(:files_info, StorageInteraction::Nextcloud::FilesInfoQuery)
register(:files, StorageInteraction::Nextcloud::FilesQuery)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,17 @@ def initialize(storage)

def call(auth_strategy:, source_path:, destination_path:)
with_tagged_logger do
valid_input_result = validate_inputs(source_path, destination_path).on_failure { return _1 }
Authentication[auth_strategy].call(storage: @storage) do |http|
valid_input_result = validate_inputs(source_path, destination_path).on_failure { return _1 }

remote_urls = build_origin_urls(**valid_input_result.result)
remote_urls = build_origin_urls(**valid_input_result.result)

ensure_remote_folder_does_not_exist(auth_strategy, remote_urls[:destination_url]).on_failure { return _1 }
ensure_remote_folder_does_not_exist(http, remote_urls[:destination_url]).on_failure { return _1 }

copy_folder(auth_strategy, **remote_urls).on_failure { return _1 }
copy_folder(http, **remote_urls).on_failure { return _1 }

get_folder_id(valid_input_result.result[:destination_path])
get_folder_id(auth_strategy, valid_input_result.result[:destination_path])
end
end
end

Expand All @@ -76,9 +78,9 @@ def build_origin_urls(source_path:, destination_path:)
{ source_url:, destination_url: }
end

def ensure_remote_folder_does_not_exist(auth_strategy, destination_url)
def ensure_remote_folder_does_not_exist(http, destination_url)
info "Checking if #{destination_url} does not already exists."
response = Authentication[auth_strategy].call(storage: @storage) { |http| http.head(destination_url) }
response = http.head(destination_url)

case response
in { status: 200..299 }
Expand All @@ -98,13 +100,11 @@ def ensure_remote_folder_does_not_exist(auth_strategy, destination_url)
end
end

def copy_folder(auth_strategy, source_url:, destination_url:)
def copy_folder(http, source_url:, destination_url:)
info "Copying #{source_url} to #{destination_url}"
response = Authentication[auth_strategy].call(storage: @storage) do |http|
http.request("COPY", source_url, headers: { "Destination" => destination_url, "Depth" => "infinity" })
end

handle_response(response)
handle_response http.request("COPY",
source_url,
headers: { "Destination" => destination_url, "Depth" => "infinity" })
end

# rubocop:disable Metrics/AbcSize
Expand Down Expand Up @@ -133,14 +133,14 @@ def handle_response(response)
errors: Util.storage_error(response:, code: :error, source:))
end
end
# rubocop:enable Metrics/AbcSize

def get_folder_id(destination_path)
call = Registry
.resolve("#{@storage.short_provider_type}.queries.file_ids")
.call(storage: @storage, path: destination_path)
# rubocop:enable Metrics/AbcSize

call.map { |result| @data.with(id: result[destination_path]["fileid"]) }
def get_folder_id(auth_strategy, destination_path)
Registry
.resolve("nextcloud.queries.file_path_to_id_map")
.call(storage: @storage, auth_strategy:, folder: ParentFolder.new(destination_path), depth: 0)
.map { |result| @data.with(id: result[destination_path].id) }
end

def source = self.class
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,24 @@ module Peripherals
module StorageInteraction
module Nextcloud
class FilePathToIdMapQuery
def self.call(storage:, auth_strategy:, folder:)
new(storage).call(auth_strategy:, folder:)
def self.call(storage:, auth_strategy:, folder:, depth: Float::INFINITY)
new(storage).call(auth_strategy:, folder:, depth:)
end

def initialize(storage)
@storage = storage
@propfind_query = Internal::PropfindQuery.new(storage)
end

def call(auth_strategy:, folder:)
def call(auth_strategy:, folder:, depth:)
origin_user_id = Util.origin_user_id(caller: self.class, storage: @storage, auth_strategy:)
.on_failure do |result|
return result
end
.on_failure { return _1 }
.result

Authentication[auth_strategy].call(storage: @storage, http_options:) do |http|
Authentication[auth_strategy].call(storage: @storage, http_options: headers(depth)) do |http|
# nc:acl-list is only required to avoid https://community.openproject.org/wp/49628. See comment #4.
@propfind_query.call(http:,
username: origin_user_id.result,
username: origin_user_id,
path: folder.path,
props: %w[oc:fileid nc:acl-list])
.map do |obj|
Expand All @@ -62,8 +61,8 @@ def call(auth_strategy:, folder:)

private

def http_options
Util.webdav_request_with_depth("infinity")
def headers(depth)
Util.webdav_request_with_depth(depth.to_s.downcase)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class FilePathToIdMapQuery
CHILDREN_FIELDS = %w[id name file folder parentReference].freeze
FOLDER_FIELDS = %w[id name parentReference].freeze

def self.call(storage:, auth_strategy:, folder:)
new(storage).call(auth_strategy:, folder:)
def self.call(storage:, auth_strategy:, folder:, depth: Float::INFINITY)
new(storage).call(auth_strategy:, folder:, depth:)
end

def initialize(storage)
Expand All @@ -46,15 +46,18 @@ def initialize(storage)
@drive_item_query = Internal::DriveItemQuery.new(storage)
end

def call(auth_strategy:, folder:)
# rubocop:disable Metrics/AbcSize
def call(auth_strategy:, folder:, depth:)
Authentication[auth_strategy].call(storage: @storage) do |http|
fetch_result = fetch_folder(http, folder)
return fetch_result if fetch_result.failure?
fetched_folder = fetch_folder(http, folder)
.on_failure { return _1 }
.result

file_ids_dictionary = fetch_result.result
file_ids_dictionary = fetched_folder
queue = [folder]
level = 0

while queue.any?
while queue.any? && level < depth
dir = queue.shift

visit = visit(http, dir)
Expand All @@ -63,12 +66,15 @@ def call(auth_strategy:, folder:)
entry, to_queue = visit.result.values_at(:entry, :to_queue)
file_ids_dictionary = file_ids_dictionary.merge(entry)
queue.concat(to_queue)
level += 1
end

ServiceResult.success(result: file_ids_dictionary)
end
end

# rubocop:enable Metrics/AbcSize

private

def visit(http, folder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ class NextcloudManagedFolderSyncService < BaseService

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",
"nextcloud.commands.add_user_to_group", "nextcloud.commands.remove_user_from_group"]
include Injector["nextcloud.commands.create_folder",
"nextcloud.commands.rename_file",
"nextcloud.commands.set_permissions",
"nextcloud.queries.group_users",
"nextcloud.queries.file_path_to_id_map",
"nextcloud.authentication.userless",
"nextcloud.commands.add_user_to_group",
"nextcloud.commands.remove_user_from_group"]

def self.i18n_key = "NextcloudSyncService"

Expand Down Expand Up @@ -76,7 +81,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(remote_folders["/#{@storage.group_folder}/"]["fileid"]).on_failure { return _1 }
ensure_root_folder_permissions(remote_folders["/#{@storage.group_folder}"].id).on_failure { return _1 }

ensure_folders_exist(remote_folders).on_success { hide_inactive_folders(remote_folders) }
end
Expand Down Expand Up @@ -169,8 +174,8 @@ def hide_inactive_folders(remote_folders)
info "Hiding folders related to inactive projects"
project_folder_ids = active_project_storages_scope.pluck(:project_folder_id).compact

remote_folders.except("/#{@storage.group_folder}/").each do |(path, attrs)|
folder_id = attrs["fileid"]
remote_folders.except("/#{@storage.group_folder}").each do |(path, file)|
folder_id = file.id

next if project_folder_ids.include?(folder_id)

Expand All @@ -196,7 +201,7 @@ def hide_inactive_folders(remote_folders)

def ensure_folders_exist(remote_folders)
info "Ensuring that automatically managed project folders exist and are correctly named."
id_folder_map = remote_folders.to_h { |folder, properties| [properties["fileid"], folder] }
id_folder_map = remote_folders.to_h { |path, file| [file.id, path] }

active_project_storages_scope.includes(:project).map do |project_storage|
unless id_folder_map.key?(project_storage.project_folder_id)
Expand All @@ -215,7 +220,7 @@ def ensure_folders_exist(remote_folders)
# @param current_path [String] current name of the remote project storage folder
# @return [ServiceResult, nil]
def rename_folder(project_storage, current_path)
return if current_path == project_storage.managed_project_folder_path
return if UrlBuilder.path(current_path) == UrlBuilder.path(project_storage.managed_project_folder_path)

name = project_storage.managed_project_folder_name
file_id = project_storage.project_folder_id
Expand Down Expand Up @@ -283,7 +288,11 @@ def ensure_root_folder_permissions(root_folder_id)

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|
file_path_to_id_map.call(storage: @storage,
auth_strategy:,
folder: Peripherals::ParentFolder.new(group_folder),
depth: 1)
.on_failure do |service_result|
log_storage_error(service_result.errors, { folder: group_folder })
add_error(:remote_folders, service_result.errors, options: { group_folder:, username: @storage.username }).fail!
end
Expand Down
Loading

0 comments on commit d63c814

Please sign in to comment.