Skip to content

Commit

Permalink
Merge pull request #15600 from opf/implementation/54553-use-authentic…
Browse files Browse the repository at this point in the history
…ation-in-upload_link_query

[#54553] reworked queries for upload link
  • Loading branch information
Kharonus committed May 17, 2024
2 parents 3b7c202 + c076d8b commit 7e5fcba
Show file tree
Hide file tree
Showing 18 changed files with 844 additions and 330 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,51 +26,56 @@
# See COPYRIGHT and LICENSE files for more details.
#++

module Storages::Peripherals::StorageInteraction::Nextcloud::Internal
class DeleteEntityCommand
Util = ::Storages::Peripherals::StorageInteraction::Nextcloud::Util
Auth = ::Storages::Peripherals::StorageInteraction::Authentication
module Storages
module Peripherals
module StorageInteraction
module Nextcloud
module Internal
class DeleteEntityCommand
def self.call(storage:, auth_strategy:, location:)
new(storage).call(auth_strategy:, location:)
end

def self.call(storage:, auth_strategy:, location:)
new(storage).call(auth_strategy:, location:)
end

def initialize(storage)
@storage = storage
end
def initialize(storage)
@storage = storage
end

def call(auth_strategy:, location:)
origin_user_id = Util.origin_user_id(caller: self.class, storage: @storage, auth_strategy:)
if origin_user_id.failure?
return origin_user_id
end
def call(auth_strategy:, location:)
origin_user_id = Util.origin_user_id(caller: self.class, storage: @storage, auth_strategy:)
if origin_user_id.failure?
return origin_user_id
end

Auth[auth_strategy].call(storage: @storage) do |http|
handle_response http.delete(Util.join_uri_path(@storage.uri,
"remote.php/dav/files",
CGI.escapeURIComponent(origin_user_id.result),
Util.escape_path(location)))
end
end
Authentication[auth_strategy].call(storage: @storage) do |http|
handle_response http.delete(Util.join_uri_path(@storage.uri,
"remote.php/dav/files",
CGI.escapeURIComponent(origin_user_id.result),
Util.escape_path(location)))
end
end

private
private

def handle_response(response)
case response
in { status: 200..299 }
ServiceResult.success
in { status: 404 }
Util.failure(code: :not_found,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request destination not found!")
in { status: 401 }
Util.failure(code: :unauthorized,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request not authorized!")
else
Util.failure(code: :error,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request failed with unknown error!")
def handle_response(response)
case response
in { status: 200..299 }
ServiceResult.success
in { status: 404 }
Util.failure(code: :not_found,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request destination not found!")
in { status: 401 }
Util.failure(code: :unauthorized,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request not authorized!")
else
Util.failure(code: :error,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request failed with unknown error!")
end
end
end
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,68 +28,72 @@
# See COPYRIGHT and LICENSE files for more details.
#++

module Storages::Peripherals::StorageInteraction::Nextcloud
class UploadLinkQuery
using Storages::Peripherals::ServiceResultRefinements
module Storages
module Peripherals
module StorageInteraction
module Nextcloud
class UploadLinkQuery
using ServiceResultRefinements

URI_TOKEN_REQUEST = "index.php/apps/integration_openproject/direct-upload-token"
URI_UPLOAD_BASE_PATH = "index.php/apps/integration_openproject/direct-upload"
def self.call(storage:, auth_strategy:, upload_data:)
new(storage).call(auth_strategy:, upload_data:)
end

def initialize(storage)
@uri = storage.uri
@configuration = storage.oauth_configuration
end
def initialize(storage)
@storage = storage
end

def self.call(storage:, user:, data:)
new(storage).call(user:, data:)
end
def call(auth_strategy:, upload_data:)
return upload_data_failure if invalid?(upload_data:)

Authentication[auth_strategy].call(storage: @storage) do |http|
response = http.post(base_uri, json: payload_from(upload_data:))

def call(user:, data:)
Util.token(user:, configuration: @configuration) do |token|
if data.nil? || data["parent"].nil?
Util.error(:error, "Data is invalid", data)
else
outbound_response(
relative_path: URI_TOKEN_REQUEST,
payload: { folder_id: data["parent"] },
token:
).map do |response|
Storages::UploadLink.new(
URI.parse(Util.join_uri_path(@uri, URI_UPLOAD_BASE_PATH, response.token))
)
handle_response(response).map do |rsp|
UploadLink.new(URI("#{upload_base_uri}/#{rsp[:token]}"), :post)
end
end
end
end
end
end

private
private

def base_uri = "#{@storage.uri}index.php/apps/integration_openproject/direct-upload-token"

def outbound_response(relative_path:, payload:, token:)
response = OpenProject
.httpx
.with(headers: { "Authorization" => "Bearer #{token.access_token}",
"Accept" => "application/json",
"Content-Type" => "application/json" })
.post(
Util.join_uri_path(@uri, relative_path),
json: payload
)
case response
in { status: 200..299 }
# The nextcloud API returns a successful response with empty body if the authorization is missing or expired
if response.body.present?
ServiceResult.success(
result: JSON.parse(response.body.to_s, object_class: OpenStruct) # rubocop:disable Style/OpenStructUse
)
else
Util.error(:unauthorized, "Outbound request not authorized!")
def upload_base_uri = "#{@storage.uri}index.php/apps/integration_openproject/direct-upload"

def upload_data_failure
Util.failure(code: :error,
data: StorageErrorData.new(source: self.class),
log_message: "Invalid upload data!")
end

def invalid?(upload_data:)
upload_data.folder_id.blank? || upload_data.file_name.blank?
end

def payload_from(upload_data:)
{ folder_id: upload_data.folder_id }
end

def handle_response(response)
case response
in { status: 200..299 }
ServiceResult.success(result: response.json(symbolize_keys: true))
in { status: 404 }
Util.failure(code: :not_found,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request destination not found!")
in { status: 401 }
Util.failure(code: :unauthorized,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request not authorized!")
else
Util.failure(code: :error,
data: Util.error_data_from_response(caller: self.class, response:),
log_message: "Outbound request failed with unknown error!")
end
end
end
in { status: 404 }
Util.error(:not_found, "Outbound request destination not found!", response)
in { status: 401 }
Util.error(:unauthorized, "Outbound request not authorized!", response)
else
Util.error(:error, "Outbound request failed!")
end
end
end
Expand Down

0 comments on commit 7e5fcba

Please sign in to comment.