Skip to content

Commit

Permalink
[#50543] Failing GRAPH API call leads to rails exception
Browse files Browse the repository at this point in the history
- https://community.openproject.org/work_packages/50543
- added new endpoints for opening storages
  - /api/v3/storages/:id/open
  - /api/v3/project_storages/:id/open
- amended queries
- amended storage representer
- added static links to open project storages from project menu
- removed open_link method from storage model
  • Loading branch information
Kharonus committed Oct 18, 2023
1 parent b59c5da commit c4b4a20
Show file tree
Hide file tree
Showing 25 changed files with 221 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ module Nextcloud
register(:propfind, Internal::PropfindQuery)
register(:group_users, GroupUsersQuery)
register(:upload_link, UploadLinkQuery)
register(:open_link, OpenLinkQuery)
register(:open_file_link, OpenFileLinkQuery)
register(:open_storage, OpenStorageQuery)
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module Storages
module Peripherals
module StorageInteraction
module Nextcloud
class OpenLinkQuery
class OpenFileLinkQuery
def initialize(storage)
@uri = storage.uri
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 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.
#++

module Storages
module Peripherals
module StorageInteraction
module Nextcloud
class OpenStorageQuery
def initialize(storage)
@uri = storage.uri
end

def self.call(storage:, user:)
new(storage).call(user:)
end

# rubocop:disable Lint/UnusedMethodArgument
def call(user:)
ServiceResult.success(result: File.join(@uri.to_s, 'index.php/apps/files'))
end

# rubocop:enable Lint/UnusedMethodArgument
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ module OneDrive
register(:files, FilesQuery)
register(:file_info, FileInfoQuery)
register(:files_info, FilesInfoQuery)
register(:open_link, OpenLinkQuery)
register(:open_drive_link, OpenDriveLinkQuery)
register(:open_file_link, OpenFileLinkQuery)
register(:open_storage, OpenStorageQuery)
register(:upload_link, UploadLinkQuery)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ module Peripherals
module StorageInteraction
module OneDrive
class FilesInfoQuery
include StorageErrorHelper

using ServiceResultRefinements

def self.call(storage:, user:, file_ids: [])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module Storages
module Peripherals
module StorageInteraction
module OneDrive
class OpenLinkQuery
class OpenFileLinkQuery
using ::Storages::Peripherals::ServiceResultRefinements

def self.call(storage:, user:, file_id:, open_location: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module Storages
module Peripherals
module StorageInteraction
module OneDrive
class OpenDriveLinkQuery
class OpenStorageQuery
def self.call(storage:, user:)
new(storage).call(user:)
end
Expand All @@ -44,13 +44,13 @@ def initialize(storage)

def call(user:)
Util.using_user_token(@storage, user) do |token|
make_request(token).map(&web_url)
request_drive(token).map(&web_url)
end
end

private

def make_request(token)
def request_drive(token)
response_data = Net::HTTP.start(@uri.host, @uri.port, use_ssl: true) do |http|
http.get(drive_uri_path, { 'Authorization' => "Bearer #{token.access_token}" })
end
Expand All @@ -60,22 +60,23 @@ def make_request(token)

def handle_responses(response)
json = MultiJson.load(response.body, symbolize_keys: true)
error_data = ::Storages::StorageErrorData.new(source: self, payload: json)

case response
when Net::HTTPSuccess
ServiceResult.success(result: json)
when Net::HTTPNotFound
ServiceResult.failure(result: :not_found,
errors: ::Storages::StorageError.new(code: :not_found, data: json))
errors: ::Storages::StorageError.new(code: :not_found, data: error_data))
when Net::HTTPForbidden
ServiceResult.failure(result: :forbidden,
errors: ::Storages::StorageError.new(code: :forbidden, data: json))
errors: ::Storages::StorageError.new(code: :forbidden, data: error_data))
when Net::HTTPUnauthorized
ServiceResult.failure(result: :unauthorized,
errors: ::Storages::StorageError.new(code: :unauthorized, data: json))
errors: ::Storages::StorageError.new(code: :unauthorized, data: error_data))
else
ServiceResult.failure(result: :error,
errors: ::Storages::StorageError.new(code: :error, data: json))
errors: ::Storages::StorageError.new(code: :error, data: error_data))
end
end

Expand Down
4 changes: 0 additions & 4 deletions modules/storages/app/models/storages/nextcloud_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ def oauth_configuration
Peripherals::OAuthConfigurations::NextcloudConfiguration.new(self)
end

def open_link
File.join(uri.to_s, 'index.php/apps/files')
end

def automatic_management_unspecified?
automatically_managed.nil?
end
Expand Down
9 changes: 0 additions & 9 deletions modules/storages/app/models/storages/one_drive_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,5 @@ def uri
def connect_src
%w[https://*.sharepoint.com https://*.up.1drv.com]
end

def open_link
::Storages::Peripherals::Registry.resolve("queries.one_drive.open_drive_link")
.call(storage: self, user: User.current)
.match(
on_success: ->(web_url) { web_url },
on_failure: ->(*) { '' }
)
end
end
end
13 changes: 0 additions & 13 deletions modules/storages/app/models/storages/project_storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,6 @@ def file_inside_project_folder?(escaped_file_path)
escaped_file_path.match?(%r|^/#{project_folder_path_escaped}|)
end

def open_link
if project_folder_inactive?
storage.open_link
else
call = ::Storages::Peripherals::Registry.resolve("queries.#{storage.short_provider_type}.open_link")
.call(storage:, user: User.current, file_id: project_folder_id)
call.match(
on_success: ->(url) { url },
on_failure: ->(*) { storage.open_link }
)
end
end

private

def escape_path(path)
Expand Down
4 changes: 0 additions & 4 deletions modules/storages/app/models/storages/storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,6 @@ def connect_src
["#{uri.scheme}://#{uri.host}"]
end

def open_link
raise Errors::SubclassResponsibility
end

def oauth_configuration
raise Errors::SubclassResponsibility
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@
#++

class API::V3::FileLinks::FileLinksOpenAPI < API::OpenProjectAPI
helpers Storages::Peripherals::StorageErrorHelper

using Storages::Peripherals::ServiceResultRefinements

resources :open do
get do
Storages::Peripherals::Registry
.resolve("queries.#{@file_link.storage.short_provider_type}.open_link")
.resolve("queries.#{@file_link.storage.short_provider_type}.open_file_link")
.call(
storage: @file_link.storage,
user: current_user,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 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.
#++

class API::V3::ProjectStorages::ProjectStorageOpenAPI < API::OpenProjectAPI
helpers Storages::Peripherals::StorageErrorHelper

using Storages::Peripherals::ServiceResultRefinements

resources :open do
get do
query_result = if @project_storage.project_folder_inactive?
Storages::Peripherals::Registry
.resolve("queries.#{@project_storage.storage.short_provider_type}.open_storage")
.call(
storage: @project_storage.storage,
user: current_user
)
else
Storages::Peripherals::Registry
.resolve("queries.#{@project_storage.storage.short_provider_type}.open_file_link")
.call(
storage: @project_storage.storage,
user: current_user,
file_id: @project_storage.project_folder_id
)
end

query_result.match(
on_success: ->(url) do
redirect url, body: "The requested resource can be viewed at #{url}"
status 303
end,
on_failure: ->(error) { raise_error(error) }
)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class ProjectStorageRepresenter < ::API::Decorators::Single
{ href: api_v3_paths.storage_file(represented.storage.id, represented.project_folder_id) }
end

link :open do
{ href: api_v3_paths.project_storage_open(represented.id) }
end

associated_resource :storage, skip_render: ->(*) { true }, skip_link: ->(*) { false }
associated_resource :project, skip_render: ->(*) { true }, skip_link: ->(*) { false }
associated_resource :creator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class ProjectStoragesAPI < API::OpenProjectAPI
end

get &API::V3::Utilities::Endpoints::Show.new(model: Storages::ProjectStorage).mount

mount API::V3::ProjectStorages::ProjectStorageOpenAPI
end
end
end
Expand Down
48 changes: 48 additions & 0 deletions modules/storages/lib/api/v3/storages/storage_open_api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2023 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.
#++

class API::V3::Storages::StorageOpenAPI < API::OpenProjectAPI
helpers Storages::Peripherals::StorageErrorHelper

using Storages::Peripherals::ServiceResultRefinements

resources :open do
get do
Storages::Peripherals::Registry
.resolve("queries.#{@storage.short_provider_type}.open_storage")
.call(storage: @storage, user: current_user, file_id: nil)
.match(
on_success: ->(url) do
redirect url, body: "The requested resource can be viewed at #{url}"
status 303
end,
on_failure: ->(error) { raise_error(error) }
)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def initialize(model, current_user:, embed_links: nil)
end

link :open do
{ href: represented.open_link }
{ href: api_v3_paths.storage_open(represented.id) }
end

link :authorizationState do
Expand Down
1 change: 1 addition & 0 deletions modules/storages/lib/api/v3/storages/storages_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class API::V3::Storages::StoragesAPI < API::OpenProjectAPI

mount API::V3::StorageFiles::StorageFilesAPI
mount API::V3::OAuthClient::OAuthClientCredentialsAPI
mount API::V3::Storages::StorageOpenAPI
end
end
end
Loading

0 comments on commit c4b4a20

Please sign in to comment.