From 90e34623660b976c527d39ef776ba679662929f9 Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Wed, 20 Sep 2023 10:43:17 +0200 Subject: [PATCH] [#49124] Implement open links for storages, file links - https://community.openproject.org/wp/49124 - added open_link method to project storages and storages - extracted open_link for file links to storage queries - polished code that shows elements with open link - storage menu items - file link list - added fallback icon matching for storages without an own icon --- .../components/storages/icons.mapping.ts | 2 +- .../storages/storage/storage.component.html | 2 +- .../storages/storage/storage.component.ts | 5 + .../storage_interaction/nextcloud.rb | 1 + .../nextcloud/open_link_query.rb} | 31 ++++-- .../storage_interaction/one_drive.rb | 2 + .../one_drive/file_info_query.rb | 46 +-------- .../one_drive/internal/drive_item_query.rb | 71 ++++++++++++++ .../one_drive/open_drive_link_query.rb | 95 +++++++++++++++++++ .../one_drive/open_link_query.rb | 63 ++++++++++++ .../app/models/storages/nextcloud_storage.rb | 6 +- .../app/models/storages/one_drive_storage.rb | 11 +++ .../app/models/storages/project_storage.rb | 20 +++- .../storages/app/models/storages/storage.rb | 4 + .../v3/file_links/file_link_representer.rb | 13 --- .../v3/file_links/file_links_download_api.rb | 2 +- .../api/v3/file_links/file_links_open_api.rb | 20 +++- .../storage_files_representer.rb | 4 +- .../api/v3/storages/storage_representer.rb | 3 +- .../lib/open_project/storages/engine.rb | 12 ++- 20 files changed, 327 insertions(+), 86 deletions(-) rename modules/storages/app/common/storages/peripherals/{storage_url_helper.rb => storage_interaction/nextcloud/open_link_query.rb} (62%) create mode 100644 modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/internal/drive_item_query.rb create mode 100644 modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_drive_link_query.rb create mode 100644 modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_link_query.rb diff --git a/frontend/src/app/shared/components/storages/icons.mapping.ts b/frontend/src/app/shared/components/storages/icons.mapping.ts index f70036089b2b..01ff93fbd3f0 100644 --- a/frontend/src/app/shared/components/storages/icons.mapping.ts +++ b/frontend/src/app/shared/components/storages/icons.mapping.ts @@ -107,5 +107,5 @@ export const fileIconMappings:Record = { export const storageIconMappings:Record = { [nextcloud]: 'nextcloud-circle', - default: 'ticket', + default: 'hosting', }; diff --git a/frontend/src/app/shared/components/storages/storage/storage.component.html b/frontend/src/app/shared/components/storages/storage/storage.component.html index ce0962680bc6..2bacde5f4c1c 100644 --- a/frontend/src/app/shared/components/storages/storage/storage.component.html +++ b/frontend/src/app/shared/components/storages/storage/storage.component.html @@ -3,7 +3,7 @@ >
storageIconMappings[storageType] || storageIconMappings.default, + }; + text = { actions: { linkExisting: this.i18n.t('js.storages.link_existing_files'), diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud.rb index 11a4d3c592b9..1ca2ebd3c0c9 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud.rb @@ -43,6 +43,7 @@ module Nextcloud register(:propfind, Internal::PropfindQuery) register(:group_users, GroupUsersQuery) register(:upload_link, UploadLinkQuery) + register(:open_link, OpenLinkQuery) end end diff --git a/modules/storages/app/common/storages/peripherals/storage_url_helper.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/open_link_query.rb similarity index 62% rename from modules/storages/app/common/storages/peripherals/storage_url_helper.rb rename to modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/open_link_query.rb index 54c435b09925..57ff7cc70ccc 100644 --- a/modules/storages/app/common/storages/peripherals/storage_url_helper.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/open_link_query.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + #-- copyright # OpenProject is an open source project management software. # Copyright (C) 2012-2023 the OpenProject GmbH @@ -26,19 +28,28 @@ # See COPYRIGHT and LICENSE files for more details. #++ -module Storages::Peripherals - # Helper for open links for a file link object. - module StorageUrlHelper - module_function +module Storages + module Peripherals + module StorageInteraction + module Nextcloud + class OpenLinkQuery + def initialize(storage) + @uri = storage.uri + end - def storage_url_open_file(storage, file_id, open_location: false) - location_flag = ActiveModel::Type::Boolean.new.cast(open_location) ? 0 : 1 + def self.call(storage:, user:, file_id:, open_location: false) + new(storage).call(user:, file_id:, open_location:) + end - "#{storage.host}/index.php/f/#{file_id}?openfile=#{location_flag}" - end + # rubocop:disable Lint/UnusedMethodArgument + def call(user:, file_id:, open_location: false) + location_flag = open_location ? 0 : 1 + ServiceResult.success(result: "#{@uri}/index.php/f/#{file_id}?openfile=#{location_flag}") + end - def storage_url_open(storage) - "#{storage.host}/index.php/apps/files" + # rubocop:enable Lint/UnusedMethodArgument + end + end end end end diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive.rb index 60096478dfd9..96b350cb1cfa 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive.rb @@ -37,6 +37,8 @@ module OneDrive register(:files, FilesQuery) register(:file_info, FileInfoQuery) register(:files_info, FilesInfoQuery) + register(:open_link, OpenLinkQuery) + register(:open_drive_link, OpenDriveLinkQuery) end end end diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/file_info_query.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/file_info_query.rb index 642c9e67f8eb..5d3a5a99a46e 100644 --- a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/file_info_query.rb +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/file_info_query.rb @@ -33,58 +33,22 @@ module Peripherals module StorageInteraction module OneDrive class FileInfoQuery - using ServiceResultRefinements + FIELDS = %w[id name fileSystemInfo file size createdBy lastModifiedBy parentReference].freeze def self.call(storage:, user:, file_id:) new(storage).call(user:, file_id:) end def initialize(storage) - @storage = storage - @uri = storage.uri + @delegate = Internal::DriveItemQuery.new(storage) end def call(user:, file_id:) - Util.using_user_token(@storage, user) do |token| - make_file_request(file_id, token).map(&storage_file_infos) - end + @delegate.call(user:, drive_item_id: file_id, fields: FIELDS).map(&storage_file_infos) end private - def make_file_request(file_id, token) - response_data = Net::HTTP.start(@uri.host, @uri.port, use_ssl: true) do |http| - http.get(uri_path_for(file_id), { 'Authorization' => "Bearer #{token.access_token}" }) - end - - handle_responses(response_data) - end - - def handle_responses(response) - json = MultiJson.load(response.body, symbolize_keys: true) - - 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)) - when Net::HTTPForbidden - ServiceResult.failure(result: :forbidden, - errors: ::Storages::StorageError.new(code: :forbidden, data: json)) - when Net::HTTPUnauthorized - ServiceResult.failure(result: :unauthorized, - errors: ::Storages::StorageError.new(code: :unauthorized, data: json)) - else - ServiceResult.failure(result: :error, - errors: ::Storages::StorageError.new(code: :error, data: json)) - end - end - - def uri_path_for(file_id) - "/v1.0/drives/#{@storage.drive_id}/items/#{file_id}" - end - def storage_file_infos ->(json) do StorageFileInfo.new( @@ -106,10 +70,6 @@ def storage_file_infos ) end end - - def parse_json(str) - MultiJson.load(str, symbolize_keys: true) - end end end end diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/internal/drive_item_query.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/internal/drive_item_query.rb new file mode 100644 index 000000000000..ab1ee734cafa --- /dev/null +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/internal/drive_item_query.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module Storages + module Peripherals + module StorageInteraction + module OneDrive + module Internal + class DriveItemQuery + UTIL = ::Storages::Peripherals::StorageInteraction::OneDrive::Util + + def self.call(storage:, user:, drive_item_id:, fields: []) + new(storage).call(user:, drive_item_id:, fields:) + end + + def initialize(storage) + @storage = storage + @uri = storage.uri + end + + def call(user:, drive_item_id:, fields: []) + select_url_query = if fields.empty? + '' + else + "?$select=#{fields.join(',')}" + end + + UTIL.using_user_token(@storage, user) do |token| + make_file_request(drive_item_id, token, select_url_query) + end + end + + private + + def make_file_request(drive_item_id, token, select_url_query) + response_data = Net::HTTP.start(@uri.host, @uri.port, use_ssl: true) do |http| + http.get(uri_path_for(drive_item_id) + select_url_query, { 'Authorization' => "Bearer #{token.access_token}" }) + end + + handle_responses(response_data) + end + + def handle_responses(response) + json = MultiJson.load(response.body, symbolize_keys: true) + + 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)) + when Net::HTTPForbidden + ServiceResult.failure(result: :forbidden, + errors: ::Storages::StorageError.new(code: :forbidden, data: json)) + when Net::HTTPUnauthorized + ServiceResult.failure(result: :unauthorized, + errors: ::Storages::StorageError.new(code: :unauthorized, data: json)) + else + ServiceResult.failure(result: :error, + errors: ::Storages::StorageError.new(code: :error, data: json)) + end + end + + def uri_path_for(file_id) + "/v1.0/drives/#{@storage.drive_id}/items/#{file_id}" + end + end + end + end + end + end +end diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_drive_link_query.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_drive_link_query.rb new file mode 100644 index 000000000000..68d48ad46e9c --- /dev/null +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_drive_link_query.rb @@ -0,0 +1,95 @@ +# 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 OneDrive + class OpenDriveLinkQuery + def self.call(storage:, user:) + new(storage).call(user:) + end + + def initialize(storage) + @storage = storage + @uri = storage.uri + end + + def call(user:) + Util.using_user_token(@storage, user) do |token| + make_request(token).map(&web_url) + end + end + + private + + def make_request(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 + + handle_responses(response_data) + end + + def handle_responses(response) + json = MultiJson.load(response.body, symbolize_keys: true) + + 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)) + when Net::HTTPForbidden + ServiceResult.failure(result: :forbidden, + errors: ::Storages::StorageError.new(code: :forbidden, data: json)) + when Net::HTTPUnauthorized + ServiceResult.failure(result: :unauthorized, + errors: ::Storages::StorageError.new(code: :unauthorized, data: json)) + else + ServiceResult.failure(result: :error, + errors: ::Storages::StorageError.new(code: :error, data: json)) + end + end + + def drive_uri_path + "/v1.0/drives/#{@storage.drive_id}?$select=webUrl" + end + + def web_url + ->(json) do + json[:webUrl] + end + end + end + end + end + end +end diff --git a/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_link_query.rb b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_link_query.rb new file mode 100644 index 000000000000..acdff069b055 --- /dev/null +++ b/modules/storages/app/common/storages/peripherals/storage_interaction/one_drive/open_link_query.rb @@ -0,0 +1,63 @@ +# 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 OneDrive + class OpenLinkQuery + def self.call(storage:, user:, file_id:, open_location: false) + new(storage).call(user:, file_id:, open_location:) + end + + def initialize(storage) + @delegate = Internal::DriveItemQuery.new(storage) + end + + # TODO: open in location + # rubocop:disable Lint/UnusedMethodArgument + def call(user:, file_id:, open_location: false) + @delegate.call(user:, drive_item_id: file_id, fields: %w[webUrl]).map(&web_url) + end + + # rubocop:enable Lint/UnusedMethodArgument + + private + + def web_url + ->(json) do + json[:webUrl] + end + end + end + end + end + end +end diff --git a/modules/storages/app/models/storages/nextcloud_storage.rb b/modules/storages/app/models/storages/nextcloud_storage.rb index 922a0a7f9665..c31f8810bbad 100644 --- a/modules/storages/app/models/storages/nextcloud_storage.rb +++ b/modules/storages/app/models/storages/nextcloud_storage.rb @@ -49,7 +49,7 @@ def self.sync_all_group_folders transaction: false) do where("provider_fields->>'automatically_managed' = 'true'") .includes(:oauth_client) - .each do |storage| + .find_each do |storage| GroupFolderPropertiesSyncService.new(storage).call end true @@ -60,6 +60,10 @@ 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 diff --git a/modules/storages/app/models/storages/one_drive_storage.rb b/modules/storages/app/models/storages/one_drive_storage.rb index ae57f9b1f3c7..3fa5f7e8fe35 100644 --- a/modules/storages/app/models/storages/one_drive_storage.rb +++ b/modules/storages/app/models/storages/one_drive_storage.rb @@ -33,6 +33,8 @@ class OneDriveStorage < Storage store_attribute :provider_fields, :tenant_id, :string, default: 'consumers' store_attribute :provider_fields, :drive_id, :string + using ::Storages::Peripherals::ServiceResultRefinements + def configuration_checks { storage_oauth_client_configured: oauth_client.present? } end @@ -44,5 +46,14 @@ def oauth_configuration def uri URI('https://graph.microsoft.com').normalize 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 diff --git a/modules/storages/app/models/storages/project_storage.rb b/modules/storages/app/models/storages/project_storage.rb index 713e2ea3d3c1..24b544dccf52 100644 --- a/modules/storages/app/models/storages/project_storage.rb +++ b/modules/storages/app/models/storages/project_storage.rb @@ -31,7 +31,8 @@ # WorkPackages in the project. # See also: file_link.rb and storage.rb class Storages::ProjectStorage < ApplicationRecord - # ProjectStorage sits between Project and Storage. + using Storages::Peripherals::ServiceResultRefinements + belongs_to :project, touch: true belongs_to :storage, touch: true, class_name: 'Storages::Storage' belongs_to :creator, class_name: 'User' @@ -63,11 +64,22 @@ 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) - ::Storages::Peripherals::StorageInteraction::Nextcloud::Util.escape_path( - path - ) + ::Storages::Peripherals::StorageInteraction::Nextcloud::Util.escape_path(path) end end diff --git a/modules/storages/app/models/storages/storage.rb b/modules/storages/app/models/storages/storage.rb index ab9f6c54c1b8..1bcb79a10356 100644 --- a/modules/storages/app/models/storages/storage.rb +++ b/modules/storages/app/models/storages/storage.rb @@ -110,6 +110,10 @@ def uri URI(host).normalize end + def open_link + raise Errors::SubclassResponsibility + end + def oauth_configuration raise Errors::SubclassResponsibility end diff --git a/modules/storages/lib/api/v3/file_links/file_link_representer.rb b/modules/storages/lib/api/v3/file_links/file_link_representer.rb index 88af64f2e06c..485167bad0e0 100644 --- a/modules/storages/lib/api/v3/file_links/file_link_representer.rb +++ b/modules/storages/lib/api/v3/file_links/file_link_representer.rb @@ -50,7 +50,6 @@ class FileLinkRepresenter < ::API::Decorators::Single include API::Decorators::LinkedResource include API::Decorators::DateProperty include ::API::Caching::CachedRepresenter - include Storages::Peripherals::StorageUrlHelper property :id @@ -90,24 +89,12 @@ class FileLinkRepresenter < ::API::Decorators::Single PERMISSION_LINKS[represented.origin_permission] end - link :originOpen do - { - href: storage_url_open_file(represented.storage, represented.origin_id) - } - end - link :staticOriginOpen do { href: api_v3_paths.file_link_open(represented.id) } end - link :originOpenLocation do - { - href: storage_url_open_file(represented.storage, represented.origin_id, open_location: true) - } - end - link :staticOriginOpenLocation do { href: api_v3_paths.file_link_open(represented.id, true) diff --git a/modules/storages/lib/api/v3/file_links/file_links_download_api.rb b/modules/storages/lib/api/v3/file_links/file_links_download_api.rb index d8e014cefb1d..45b4d316bf0e 100644 --- a/modules/storages/lib/api/v3/file_links/file_links_download_api.rb +++ b/modules/storages/lib/api/v3/file_links/file_links_download_api.rb @@ -30,7 +30,7 @@ class API::V3::FileLinks::FileLinksDownloadAPI < API::OpenProjectAPI using Storages::Peripherals::ServiceResultRefinements - helpers Storages::Peripherals::StorageUrlHelper, Storages::Peripherals::StorageErrorHelper + helpers Storages::Peripherals::StorageErrorHelper resources :download do get do diff --git a/modules/storages/lib/api/v3/file_links/file_links_open_api.rb b/modules/storages/lib/api/v3/file_links/file_links_open_api.rb index 70d29ac6a5ed..e721ac5d4bef 100644 --- a/modules/storages/lib/api/v3/file_links/file_links_open_api.rb +++ b/modules/storages/lib/api/v3/file_links/file_links_open_api.rb @@ -27,13 +27,25 @@ #++ class API::V3::FileLinks::FileLinksOpenAPI < API::OpenProjectAPI - helpers Storages::Peripherals::StorageUrlHelper + using Storages::Peripherals::ServiceResultRefinements resources :open do get do - url = storage_url_open_file(@file_link.storage, @file_link.origin_id, open_location: params[:location]) - redirect url, body: "The requested resource can be viewed at #{url}" - status 303 # The follow-up request to the resource must be GET + Storages::Peripherals::Registry + .resolve("queries.#{@file_link.storage.short_provider_type}.open_link") + .call( + storage: @file_link.storage, + user: current_user, + file_id: @file_link.origin_id, + open_location: ActiveModel::Type::Boolean.new.cast(params[:location]) + ) + .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 diff --git a/modules/storages/lib/api/v3/storage_files/storage_files_representer.rb b/modules/storages/lib/api/v3/storage_files/storage_files_representer.rb index b392ca9a759b..3d27ffe462bf 100644 --- a/modules/storages/lib/api/v3/storage_files/storage_files_representer.rb +++ b/modules/storages/lib/api/v3/storage_files/storage_files_representer.rb @@ -47,7 +47,9 @@ def initialize(model, storage, current_user:) exec_context: :decorator property :parent, - getter: ->(*) { API::V3::StorageFiles::StorageFileRepresenter.new(represented.parent, @storage, current_user:) }, + getter: ->(*) do + API::V3::StorageFiles::StorageFileRepresenter.new(represented.parent, @storage, current_user:) + end, exec_context: :decorator collection :ancestors, diff --git a/modules/storages/lib/api/v3/storages/storage_representer.rb b/modules/storages/lib/api/v3/storages/storage_representer.rb index b4f78a6815f7..c9fa7ed5afe6 100644 --- a/modules/storages/lib/api/v3/storages/storage_representer.rb +++ b/modules/storages/lib/api/v3/storages/storage_representer.rb @@ -51,7 +51,6 @@ class StorageRepresenter < ::API::Decorators::Single # LinkedResource module defines helper methods to describe attributes include API::Decorators::LinkedResource include API::Decorators::DateProperty - include Storages::Peripherals::StorageUrlHelper module ClassMethods private @@ -149,7 +148,7 @@ def initialize(model, current_user:, embed_links: nil) end link :open do - { href: storage_url_open(represented) } + { href: represented.open_link } end link :authorizationState do diff --git a/modules/storages/lib/open_project/storages/engine.rb b/modules/storages/lib/open_project/storages/engine.rb index ade205c48044..a6b3ca29b4c3 100644 --- a/modules/storages/lib/open_project/storages/engine.rb +++ b/modules/storages/lib/open_project/storages/engine.rb @@ -35,6 +35,7 @@ class Engine < ::Rails::Engine def self.permissions @permissions ||= Storages::GroupFolderPropertiesSyncService::PERMISSIONS_KEYS end + # engine name is used as a default prefix for module tables when generating # tables with the rails command. # It may also be used in other places, please investigate. @@ -157,10 +158,11 @@ def self.permissions User.current.allowed_to?(:view_file_links, project) project.project_storages.each do |project_storage| storage = project_storage.storage - href = if project_storage.project_folder_inactive? - storage.host + href = project_storage.open_link + icon = if storage.provider_type_nextcloud? + 'nextcloud-circle' else - ::Storages::Peripherals::StorageUrlHelper.storage_url_open_file(storage, project_storage.project_folder_id) + 'hosting' end menu.push( @@ -168,8 +170,8 @@ def self.permissions href, caption: storage.name, before: :members, - icon: "#{storage.short_provider_type}-circle", - icon_after: "external-link", + icon:, + icon_after: 'external-link', skip_permissions_check: true ) end