mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
[#49124] added new unit tests and fixed changed ones
This commit is contained in:
+1
-1
@@ -343,7 +343,7 @@ ij_json_keep_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
ij_json_space_after_colon = true
|
||||
ij_json_space_after_comma = true
|
||||
ij_json_space_before_colon = true
|
||||
ij_json_space_before_colon = false
|
||||
ij_json_space_before_comma = false
|
||||
ij_json_spaces_within_braces = false
|
||||
ij_json_spaces_within_brackets = false
|
||||
|
||||
+27
-5
@@ -33,6 +33,8 @@ module Storages
|
||||
module StorageInteraction
|
||||
module OneDrive
|
||||
class OpenLinkQuery
|
||||
using ::Storages::Peripherals::ServiceResultRefinements
|
||||
|
||||
def self.call(storage:, user:, file_id:, open_location: false)
|
||||
new(storage).call(user:, file_id:, open_location:)
|
||||
end
|
||||
@@ -41,21 +43,41 @@ module Storages
|
||||
@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)
|
||||
@user = user
|
||||
|
||||
if open_location
|
||||
request_parent_id.call(file_id) >> request_web_url
|
||||
else
|
||||
request_web_url.call(file_id)
|
||||
end
|
||||
end
|
||||
|
||||
# rubocop:enable Lint/UnusedMethodArgument
|
||||
|
||||
private
|
||||
|
||||
def request_web_url
|
||||
->(file_id) do
|
||||
@delegate.call(user: @user, drive_item_id: file_id, fields: %w[webUrl]).map(&web_url)
|
||||
end
|
||||
end
|
||||
|
||||
def request_parent_id
|
||||
->(file_id) do
|
||||
@delegate.call(user: @user, drive_item_id: file_id, fields: %w[parentReference]).map(&parent_id)
|
||||
end
|
||||
end
|
||||
|
||||
def web_url
|
||||
->(json) do
|
||||
json[:webUrl]
|
||||
end
|
||||
end
|
||||
|
||||
def parent_id
|
||||
->(json) do
|
||||
json.dig(:parentReference, :id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
require 'spec_helper'
|
||||
require_module_spec_helper
|
||||
|
||||
RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::OpenLinkQuery do
|
||||
include JsonResponseHelper
|
||||
|
||||
let(:storage) { create(:nextcloud_storage, host: 'https://example.com/html') }
|
||||
let(:user) { create(:user) }
|
||||
let(:file_id) { '1337' }
|
||||
|
||||
it 'responds to .call' do
|
||||
expect(described_class).to respond_to(:call)
|
||||
|
||||
method = described_class.method(:call)
|
||||
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user], %i[keyreq file_id], %i[key open_location])
|
||||
end
|
||||
|
||||
it 'returns the url for opening the file on storage' do
|
||||
url = described_class.call(storage:, user:, file_id:).result
|
||||
expect(url).to eq("#{storage.host}/index.php/f/#{file_id}?openfile=1")
|
||||
end
|
||||
|
||||
it 'returns the url for opening the file\'s location on storage' do
|
||||
url = described_class.call(storage:, user:, file_id:, open_location: true).result
|
||||
expect(url).to eq("#{storage.host}/index.php/f/#{file_id}?openfile=0")
|
||||
end
|
||||
end
|
||||
+6
-8
@@ -45,12 +45,6 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FileInfoQuer
|
||||
let(:not_found_json) { not_found_response }
|
||||
let(:forbidden_json) { forbidden_response }
|
||||
|
||||
before do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('folder_drive_item'), headers: {})
|
||||
end
|
||||
|
||||
it 'responds to .call' do
|
||||
expect(described_class).to respond_to(:call)
|
||||
|
||||
@@ -59,6 +53,10 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FileInfoQuer
|
||||
end
|
||||
|
||||
it 'returns a storage file info object' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('folder_drive_item'), headers: {})
|
||||
|
||||
storage_file_info = described_class.call(storage:, user:, file_id:).result
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
@@ -84,7 +82,7 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FileInfoQuer
|
||||
|
||||
describe 'error handling' do
|
||||
it 'returns a notfound error if the API call returns a 404' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 404, body: not_found_json, headers: {})
|
||||
|
||||
@@ -96,7 +94,7 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FileInfoQuer
|
||||
end
|
||||
|
||||
it 'returns a forbidden error if the API call returns a 403' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 403, body: forbidden_json, headers: {})
|
||||
|
||||
|
||||
+13
-15
@@ -44,8 +44,8 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FilesInfoQue
|
||||
let(:file_ids) do
|
||||
%w(
|
||||
01BYE5RZ5MYLM2SMX75ZBIPQZIHT6OAYPB
|
||||
01BYE5RZZ6FUE5272C5JCY3L7CLZ7XOUYM
|
||||
01BYE5RZ47DTJGHO73WBH2ONNXQZVNNILJ
|
||||
01BYE5RZ7T3DFLFS6TCRH2QAPWXL5APDLE
|
||||
01BYE5RZ4VAJVBMWSWINA2QYFFNZ2GL3O5
|
||||
not_existent
|
||||
forbidden
|
||||
)
|
||||
@@ -54,19 +54,19 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FilesInfoQue
|
||||
let(:forbidden_json) { forbidden_response }
|
||||
|
||||
before do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[0]}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[0]}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('folder_drive_item'), headers: {})
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[1]}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[1]}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('file_drive_item_1'), headers: {})
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[2]}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[2]}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('file_drive_item_2'), headers: {})
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[3]}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[3]}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 404, body: not_found_json, headers: {})
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[4]}")
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_ids[4]}?$select=id,name,fileSystemInfo,file,size,createdBy,lastModifiedBy,parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 403, body: forbidden_json, headers: {})
|
||||
end
|
||||
@@ -111,25 +111,23 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FilesInfoQue
|
||||
it 'returns a file storage file info object' do
|
||||
storage_file_info = described_class.call(storage:, user:, file_ids: file_ids.slice(1, 1)).result[0]
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
expect(storage_file_info.to_h).to eq({
|
||||
status: 'ok',
|
||||
status_code: 200,
|
||||
id: '01BYE5RZZ6FUE5272C5JCY3L7CLZ7XOUYM',
|
||||
name: 'All Japan Revenues By City.xlsx',
|
||||
size: 20051,
|
||||
id: '01BYE5RZ7T3DFLFS6TCRH2QAPWXL5APDLE',
|
||||
name: 'Popular Mixed Drinks.xlsx',
|
||||
size: 7064929,
|
||||
mime_type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
created_at: Time.parse('2017-08-07T16:07:10Z'),
|
||||
last_modified_at: Time.parse('2017-08-07T16:07:10Z'),
|
||||
created_at: Time.parse('2017-08-07T16:16:53Z'),
|
||||
last_modified_at: Time.parse('2017-08-07T16:16:53Z'),
|
||||
owner_name: 'Megan Bowen',
|
||||
owner_id: '48d31887-5fad-4d73-a9f5-3c356e68a038',
|
||||
last_modified_by_id: '48d31887-5fad-4d73-a9f5-3c356e68a038',
|
||||
last_modified_by_name: 'Megan Bowen',
|
||||
permissions: nil,
|
||||
trashed: false,
|
||||
location: '/drives/b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd/root:'
|
||||
location: '/drive/root:/Business Data'
|
||||
})
|
||||
# rubocop:enable Layout/LineLength
|
||||
end
|
||||
|
||||
it 'returns an error storage file info object for not found' do
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::FilesQuery,
|
||||
drive_id: 'b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')
|
||||
end
|
||||
let(:user) { create(:user) }
|
||||
let(:json) { read_json('root_drive') }
|
||||
let(:json) { read_json('root_drive_children') }
|
||||
let(:token) { create(:oauth_client_token, user:, oauth_client: storage.oauth_client) }
|
||||
|
||||
it 'responds to .call' do
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
require 'spec_helper'
|
||||
require_module_spec_helper
|
||||
|
||||
RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::OpenDriveLinkQuery, :webmock do
|
||||
include JsonResponseHelper
|
||||
|
||||
let(:storage) do
|
||||
create(:one_drive_storage,
|
||||
:with_oauth_client,
|
||||
drive_id: 'b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')
|
||||
end
|
||||
let(:user) { create(:user) }
|
||||
let(:token) { create(:oauth_client_token, user:, oauth_client: storage.oauth_client) }
|
||||
let(:not_found_json) { not_found_response }
|
||||
let(:forbidden_json) { forbidden_response }
|
||||
|
||||
it 'responds to .call' do
|
||||
expect(described_class).to respond_to(:call)
|
||||
|
||||
method = described_class.method(:call)
|
||||
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user])
|
||||
end
|
||||
|
||||
it 'returns the url for opening the drive root on storage' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('root_drive'), headers: {})
|
||||
|
||||
url = described_class.call(storage:, user:).result
|
||||
expect(url).to eq('https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents')
|
||||
end
|
||||
|
||||
describe 'error handling' do
|
||||
it 'returns a notfound error if the API call returns a 404' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 404, body: not_found_json, headers: {})
|
||||
|
||||
open_drive_link_result = described_class.call(storage:, user:)
|
||||
|
||||
expect(open_drive_link_result).to be_failure
|
||||
expect(open_drive_link_result.result).to eq(:not_found)
|
||||
expect(open_drive_link_result.errors.data.to_json).to eq(not_found_json)
|
||||
end
|
||||
|
||||
it 'returns a forbidden error if the API call returns a 403' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 403, body: forbidden_json, headers: {})
|
||||
|
||||
open_drive_link_result = described_class.call(storage:, user:)
|
||||
|
||||
expect(open_drive_link_result).to be_failure
|
||||
expect(open_drive_link_result.result).to eq(:forbidden)
|
||||
expect(open_drive_link_result.errors.data.to_json).to eq(forbidden_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
# 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.
|
||||
#++
|
||||
|
||||
require 'spec_helper'
|
||||
require_module_spec_helper
|
||||
|
||||
RSpec.describe Storages::Peripherals::StorageInteraction::OneDrive::OpenLinkQuery, :webmock do
|
||||
include JsonResponseHelper
|
||||
|
||||
let(:storage) do
|
||||
create(:one_drive_storage,
|
||||
:with_oauth_client,
|
||||
drive_id: 'b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')
|
||||
end
|
||||
let(:user) { create(:user) }
|
||||
let(:token) { create(:oauth_client_token, user:, oauth_client: storage.oauth_client) }
|
||||
let(:folder_id) { '01BYE5RZ5MYLM2SMX75ZBIPQZIHT6OAYPB' }
|
||||
let(:file_id) { '01BYE5RZ7T3DFLFS6TCRH2QAPWXL5APDLE' }
|
||||
let(:not_found_json) { not_found_response }
|
||||
let(:forbidden_json) { forbidden_response }
|
||||
|
||||
it 'responds to .call' do
|
||||
expect(described_class).to respond_to(:call)
|
||||
|
||||
method = described_class.method(:call)
|
||||
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq user], %i[keyreq file_id], %i[key open_location])
|
||||
end
|
||||
|
||||
it 'returns the url for opening the file on storage' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('file_drive_item_1'), headers: {})
|
||||
|
||||
url = described_class.call(storage:, user:, file_id:).result
|
||||
expect(url).to eq('https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7BB2CAD8F3-D3CB-4F14-A801-F6BAFA078D64%7D&file=Popular%20Mixed%20Drinks.xlsx&action=default&mobileredirect=true')
|
||||
end
|
||||
|
||||
it 'returns the url for opening the file\'s location on storage' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=parentReference")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('file_drive_item_1'), headers: {})
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{folder_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 200, body: read_json('folder_drive_item'), headers: {})
|
||||
|
||||
url = described_class.call(storage:, user:, file_id:, open_location: true).result
|
||||
expect(url).to eq('https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents/Business%20Data')
|
||||
end
|
||||
|
||||
describe 'error handling' do
|
||||
it 'returns a notfound error if the API call returns a 404' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 404, body: not_found_json, headers: {})
|
||||
|
||||
open_link_result = described_class.call(storage:, user:, file_id:)
|
||||
|
||||
expect(open_link_result).to be_failure
|
||||
expect(open_link_result.result).to eq(:not_found)
|
||||
expect(open_link_result.errors.data.to_json).to eq(not_found_json)
|
||||
end
|
||||
|
||||
it 'returns a forbidden error if the API call returns a 403' do
|
||||
stub_request(:get, "https://graph.microsoft.com/v1.0/drives/#{storage.drive_id}/items/#{file_id}?$select=webUrl")
|
||||
.with(headers: { 'Authorization' => "Bearer #{token.access_token}" })
|
||||
.to_return(status: 403, body: forbidden_json, headers: {})
|
||||
|
||||
open_link_result = described_class.call(storage:, user:, file_id:)
|
||||
|
||||
expect(open_link_result).to be_failure
|
||||
expect(open_link_result.result).to eq(:forbidden)
|
||||
expect(open_link_result.errors.data.to_json).to eq(forbidden_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -125,13 +125,6 @@ RSpec.describe API::V3::FileLinks::FileLinkRepresenter, 'rendering' do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'originOpen' do
|
||||
it_behaves_like 'has an untitled link' do
|
||||
let(:link) { 'originOpen' }
|
||||
let(:href) { "#{storage.host}/index.php/f/#{file_link.origin_id}?openfile=1" }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'staticOriginOpen' do
|
||||
it_behaves_like 'has an untitled link' do
|
||||
let(:link) { 'staticOriginOpen' }
|
||||
@@ -139,13 +132,6 @@ RSpec.describe API::V3::FileLinks::FileLinkRepresenter, 'rendering' do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'originOpenLocation' do
|
||||
it_behaves_like 'has an untitled link' do
|
||||
let(:link) { 'originOpenLocation' }
|
||||
let(:href) { "#{storage.host}/index.php/f/#{file_link.origin_id}?openfile=0" }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'staticOriginOpenLocation' do
|
||||
it_behaves_like 'has an untitled link' do
|
||||
let(:link) { 'staticOriginOpenLocation' }
|
||||
|
||||
@@ -266,6 +266,12 @@ RSpec.describe API::V3::Storages::StorageRepresenter, 'rendering' do
|
||||
build(:one_drive_storage, oauth_application:, oauth_client: oauth_client_credentials)
|
||||
end
|
||||
|
||||
before do
|
||||
Storages::Peripherals::Registry.stub('queries.one_drive.open_drive_link', ->(_) do
|
||||
ServiceResult.success(result: 'https://my.sharepoint.com/sites/DeathStar/Documents')
|
||||
end)
|
||||
end
|
||||
|
||||
it 'does not include the property hasApplicationPassword' do
|
||||
expect(generated).not_to have_json_path('hasApplicationPassword')
|
||||
end
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('48d31887-5fad-4d73-a9f5-3c356e68a038')/drives('b%21-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')/items/$entity",
|
||||
"@microsoft.graph.downloadUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/download.aspx?UniqueId=dd092d3e-427f-45ea-8daf-e25e7f77530c&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgyMTQzNTUtbXkuc2hhcmVwb2ludC5jb21AZGNkMjE5ZGQtYmM2OC00YjliLWJmMGItNGEzM2E3OTZiZTM1IiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTY5NDA5MjIxNyIsImV4cCI6IjE2OTQwOTU4MTciLCJlbmRwb2ludHVybCI6IjlacHYvK25wK3ExWnFXdnlMM2RZNGVVaHdtMlllaHJvRTlBSmFjOC84R2c9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxNjkiLCJpc2xvb3BiYWNrIjoiVHJ1ZSIsImNpZCI6IjRmalZ5bnFqTUU2QXNZaUhrUjhJc1E9PSIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJaRGd5TXpFeVpqa3RZakl6WWkwMFkySmpMVGsxWkRVdE0yVXdaRGswWlRZNFl6RmwiLCJhcHBfZGlzcGxheW5hbWUiOiJhcGlzYW5kYm94cHJveHkiLCJnaXZlbl9uYW1lIjoiTWVnYW4iLCJmYW1pbHlfbmFtZSI6IkJvd2VuIiwiYXBwaWQiOiIwNWIxMGEyZC02MmRiLTQyMGMtODYyNi01NWYzYTVlNzg2NWIiLCJ0aWQiOiJkY2QyMTlkZC1iYzY4LTRiOWItYmYwYi00YTMzYTc5NmJlMzUiLCJ1cG4iOiJtZWdhbmJAbTM2NXgyMTQzNTUub25taWNyb3NvZnQuY29tIiwicHVpZCI6IjEwMDNCRkZEQTM4MTMxQUYiLCJjYWNoZWtleSI6IjBoLmZ8bWVtYmVyc2hpcHwxMDAzYmZmZGEzODEzMWFmQGxpdmUuY29tIiwic2NwIjoibXlmaWxlcy5yZWFkIGdyb3VwLnJlYWQgYWxsc2l0ZXMucmVhZCBhbGxwcm9maWxlcy5yZWFkIGFsbHByb2ZpbGVzLnJlYWQgdGVybXN0b3JlLnJlYWQiLCJ0dCI6IjIiLCJpcGFkZHIiOiIyMC4xOTAuMTY5LjE2MCJ9.P2hyTGx96JOTh3_8HyKyNkUOvUh88nZmRGmDbxDMQaE&ApiVersion=2.0",
|
||||
"createdDateTime": "2017-08-07T16:07:10Z",
|
||||
"eTag": "\"{DD092D3E-427F-45EA-8DAF-E25E7F77530C},3\"",
|
||||
"id": "01BYE5RZZ6FUE5272C5JCY3L7CLZ7XOUYM",
|
||||
"lastModifiedDateTime": "2017-08-07T16:07:10Z",
|
||||
"name": "All Japan Revenues By City.xlsx",
|
||||
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7BDD092D3E-427F-45EA-8DAF-E25E7F77530C%7D&file=All%20Japan%20Revenues%20By%20City.xlsx&action=default&mobileredirect=true",
|
||||
"cTag": "\"c:{DD092D3E-427F-45EA-8DAF-E25E7F77530C},1\"",
|
||||
"size": 20051,
|
||||
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('48d31887-5fad-4d73-a9f5-3c356e68a038')/drive/items/$entity",
|
||||
"@microsoft.graph.downloadUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/download.aspx?UniqueId=b2cad8f3-d3cb-4f14-a801-f6bafa078d64&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgyMTQzNTUtbXkuc2hhcmVwb2ludC5jb21AZGNkMjE5ZGQtYmM2OC00YjliLWJmMGItNGEzM2E3OTZiZTM1IiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTY5NTIwNzI4MSIsImV4cCI6IjE2OTUyMTA4ODEiLCJlbmRwb2ludHVybCI6Ii85bTNxeGlHT1ZBQWxldjhkMmttNG96aktvck55VGlrdTYrZzRQNTFJUnM9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxNjkiLCJpc2xvb3BiYWNrIjoiVHJ1ZSIsImNpZCI6IkttRk1WN3JTVzBDS1RJRzNFRVArY1E9PSIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJaRGd5TXpFeVpqa3RZakl6WWkwMFkySmpMVGsxWkRVdE0yVXdaRGswWlRZNFl6RmwiLCJhcHBfZGlzcGxheW5hbWUiOiJhcGlzYW5kYm94cHJveHkiLCJnaXZlbl9uYW1lIjoiTWVnYW4iLCJmYW1pbHlfbmFtZSI6IkJvd2VuIiwiYXBwaWQiOiIwNWIxMGEyZC02MmRiLTQyMGMtODYyNi01NWYzYTVlNzg2NWIiLCJ0aWQiOiJkY2QyMTlkZC1iYzY4LTRiOWItYmYwYi00YTMzYTc5NmJlMzUiLCJ1cG4iOiJtZWdhbmJAbTM2NXgyMTQzNTUub25taWNyb3NvZnQuY29tIiwicHVpZCI6IjEwMDNCRkZEQTM4MTMxQUYiLCJjYWNoZWtleSI6IjBoLmZ8bWVtYmVyc2hpcHwxMDAzYmZmZGEzODEzMWFmQGxpdmUuY29tIiwic2NwIjoibXlmaWxlcy5yZWFkIGdyb3VwLnJlYWQgYWxsc2l0ZXMucmVhZCBhbGxwcm9maWxlcy5yZWFkIGFsbHByb2ZpbGVzLnJlYWQgdGVybXN0b3JlLnJlYWQiLCJ0dCI6IjIiLCJpcGFkZHIiOiI0MC4xMjYuNDEuOTYifQ._a-C996692KBUCD7GF5ZQtwoemiL_lw4qVMt0E7Jhzc&ApiVersion=2.0",
|
||||
"createdDateTime": "2017-08-07T16:16:53Z",
|
||||
"eTag": "\"{B2CAD8F3-D3CB-4F14-A801-F6BAFA078D64},2\"",
|
||||
"id": "01BYE5RZ7T3DFLFS6TCRH2QAPWXL5APDLE",
|
||||
"lastModifiedDateTime": "2017-08-07T16:16:53Z",
|
||||
"name": "Popular Mixed Drinks.xlsx",
|
||||
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7BB2CAD8F3-D3CB-4F14-A801-F6BAFA078D64%7D&file=Popular%20Mixed%20Drinks.xlsx&action=default&mobileredirect=true",
|
||||
"cTag": "\"c:{B2CAD8F3-D3CB-4F14-A801-F6BAFA078D64},1\"",
|
||||
"size": 7064929,
|
||||
"createdBy": {
|
||||
"user": {
|
||||
"email": "MeganB@M365x214355.onmicrosoft.com",
|
||||
@@ -26,21 +26,18 @@
|
||||
"parentReference": {
|
||||
"driveType": "business",
|
||||
"driveId": "b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd",
|
||||
"id": "01BYE5RZ56Y2GOVW7725BZO354PWSELRRZ",
|
||||
"path": "/drives/b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd/root:",
|
||||
"id": "01BYE5RZ5MYLM2SMX75ZBIPQZIHT6OAYPB",
|
||||
"path": "/drive/root:/Business Data",
|
||||
"siteId": "d82312f9-b23b-4cbc-95d5-3e0d94e68c1e"
|
||||
},
|
||||
"file": {
|
||||
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"hashes": {
|
||||
"quickXorHash": "I1snetixdavVoAQ0QMvy/W1dyhs="
|
||||
"quickXorHash": "IQcTRezR55cAlOtZGiOF33CuqMU="
|
||||
}
|
||||
},
|
||||
"fileSystemInfo": {
|
||||
"createdDateTime": "2017-08-07T16:07:10Z",
|
||||
"lastModifiedDateTime": "2017-08-07T16:07:10Z"
|
||||
},
|
||||
"shared": {
|
||||
"scope": "users"
|
||||
"createdDateTime": "2017-08-07T16:16:53Z",
|
||||
"lastModifiedDateTime": "2017-08-07T16:16:53Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('48d31887-5fad-4d73-a9f5-3c356e68a038')/drives('b%21-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd')/items/$entity",
|
||||
"@microsoft.graph.downloadUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/download.aspx?UniqueId=63d21c9f-fbbb-4fb0-a735-b7866ad6a169&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgyMTQzNTUtbXkuc2hhcmVwb2ludC5jb21AZGNkMjE5ZGQtYmM2OC00YjliLWJmMGItNGEzM2E3OTZiZTM1IiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTY5NDA5MjIzNCIsImV4cCI6IjE2OTQwOTU4MzQiLCJlbmRwb2ludHVybCI6Ik1BT3pvbGh5VURRMzhnSEEyajhQS1NoU2dzY015WlZBWlN3d1VsRDBOYkk9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxNjkiLCJpc2xvb3BiYWNrIjoiVHJ1ZSIsImNpZCI6IjJCR1dDemVJZkVta05RRVVKaFVubmc9PSIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJaRGd5TXpFeVpqa3RZakl6WWkwMFkySmpMVGsxWkRVdE0yVXdaRGswWlRZNFl6RmwiLCJhcHBfZGlzcGxheW5hbWUiOiJhcGlzYW5kYm94cHJveHkiLCJnaXZlbl9uYW1lIjoiTWVnYW4iLCJmYW1pbHlfbmFtZSI6IkJvd2VuIiwiYXBwaWQiOiIwNWIxMGEyZC02MmRiLTQyMGMtODYyNi01NWYzYTVlNzg2NWIiLCJ0aWQiOiJkY2QyMTlkZC1iYzY4LTRiOWItYmYwYi00YTMzYTc5NmJlMzUiLCJ1cG4iOiJtZWdhbmJAbTM2NXgyMTQzNTUub25taWNyb3NvZnQuY29tIiwicHVpZCI6IjEwMDNCRkZEQTM4MTMxQUYiLCJjYWNoZWtleSI6IjBoLmZ8bWVtYmVyc2hpcHwxMDAzYmZmZGEzODEzMWFmQGxpdmUuY29tIiwic2NwIjoibXlmaWxlcy5yZWFkIGdyb3VwLnJlYWQgYWxsc2l0ZXMucmVhZCBhbGxwcm9maWxlcy5yZWFkIGFsbHByb2ZpbGVzLnJlYWQgdGVybXN0b3JlLnJlYWQiLCJ0dCI6IjIiLCJpcGFkZHIiOiIyMC4xOTAuMTY5LjE2MCJ9.E8yDmydDqhGRNq-c0sLJ7UYrKMx7g3TwF15wV4djDiI&ApiVersion=2.0",
|
||||
"createdDateTime": "2017-08-07T16:08:22Z",
|
||||
"eTag": "\"{63D21C9F-FBBB-4FB0-A735-B7866AD6A169},4\"",
|
||||
"id": "01BYE5RZ47DTJGHO73WBH2ONNXQZVNNILJ",
|
||||
"lastModifiedDateTime": "2017-08-07T16:08:22Z",
|
||||
"name": "BrokenPipe.jpg",
|
||||
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/Documents/BrokenPipe.jpg",
|
||||
"cTag": "\"c:{63D21C9F-FBBB-4FB0-A735-B7866AD6A169},1\"",
|
||||
"size": 5336,
|
||||
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('48d31887-5fad-4d73-a9f5-3c356e68a038')/drive/items/$entity",
|
||||
"@microsoft.graph.downloadUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/download.aspx?UniqueId=166a0295-565a-4143-a860-a56e7465eddd&Translate=false&tempauth=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIwMDAwMDAwMy0wMDAwLTBmZjEtY2UwMC0wMDAwMDAwMDAwMDAvbTM2NXgyMTQzNTUtbXkuc2hhcmVwb2ludC5jb21AZGNkMjE5ZGQtYmM2OC00YjliLWJmMGItNGEzM2E3OTZiZTM1IiwiaXNzIjoiMDAwMDAwMDMtMDAwMC0wZmYxLWNlMDAtMDAwMDAwMDAwMDAwIiwibmJmIjoiMTY5NTIwNzMyMyIsImV4cCI6IjE2OTUyMTA5MjMiLCJlbmRwb2ludHVybCI6ImVJMm5GNENSQ05jKytya05oeGMrY0NLbXVIalJPZDBybVFLNTJCb1g3Mms9IiwiZW5kcG9pbnR1cmxMZW5ndGgiOiIxNjkiLCJpc2xvb3BiYWNrIjoiVHJ1ZSIsImNpZCI6Im1RSDA0RjdZaUVLUExOMlJYckMrL2c9PSIsInZlciI6Imhhc2hlZHByb29mdG9rZW4iLCJzaXRlaWQiOiJaRGd5TXpFeVpqa3RZakl6WWkwMFkySmpMVGsxWkRVdE0yVXdaRGswWlRZNFl6RmwiLCJhcHBfZGlzcGxheW5hbWUiOiJhcGlzYW5kYm94cHJveHkiLCJnaXZlbl9uYW1lIjoiTWVnYW4iLCJmYW1pbHlfbmFtZSI6IkJvd2VuIiwiYXBwaWQiOiIwNWIxMGEyZC02MmRiLTQyMGMtODYyNi01NWYzYTVlNzg2NWIiLCJ0aWQiOiJkY2QyMTlkZC1iYzY4LTRiOWItYmYwYi00YTMzYTc5NmJlMzUiLCJ1cG4iOiJtZWdhbmJAbTM2NXgyMTQzNTUub25taWNyb3NvZnQuY29tIiwicHVpZCI6IjEwMDNCRkZEQTM4MTMxQUYiLCJjYWNoZWtleSI6IjBoLmZ8bWVtYmVyc2hpcHwxMDAzYmZmZGEzODEzMWFmQGxpdmUuY29tIiwic2NwIjoibXlmaWxlcy5yZWFkIGdyb3VwLnJlYWQgYWxsc2l0ZXMucmVhZCBhbGxwcm9maWxlcy5yZWFkIGFsbHByb2ZpbGVzLnJlYWQgdGVybXN0b3JlLnJlYWQiLCJ0dCI6IjIiLCJpcGFkZHIiOiI0MC4xMjYuNDEuOTYifQ.mszZL3eBLbQwsCXjEhEbXONqlxLcjYs3Gw6YGO4s02Y&ApiVersion=2.0",
|
||||
"createdDateTime": "2017-08-07T16:17:09Z",
|
||||
"eTag": "\"{166A0295-565A-4143-A860-A56E7465EDDD},2\"",
|
||||
"id": "01BYE5RZ4VAJVBMWSWINA2QYFFNZ2GL3O5",
|
||||
"lastModifiedDateTime": "2017-08-07T16:17:09Z",
|
||||
"name": "Retail Store Analysis.xlsx",
|
||||
"webUrl": "https://m365x214355-my.sharepoint.com/personal/meganb_m365x214355_onmicrosoft_com/_layouts/15/Doc.aspx?sourcedoc=%7B166A0295-565A-4143-A860-A56E7465EDDD%7D&file=Retail%20Store%20Analysis.xlsx&action=default&mobileredirect=true",
|
||||
"cTag": "\"c:{166A0295-565A-4143-A860-A56E7465EDDD},1\"",
|
||||
"size": 11282101,
|
||||
"createdBy": {
|
||||
"user": {
|
||||
"email": "MeganB@M365x214355.onmicrosoft.com",
|
||||
@@ -26,26 +26,18 @@
|
||||
"parentReference": {
|
||||
"driveType": "business",
|
||||
"driveId": "b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd",
|
||||
"id": "01BYE5RZ56Y2GOVW7725BZO354PWSELRRZ",
|
||||
"path": "/drives/b!-RIj2DuyvEyV1T4NlOaMHk8XkS_I8MdFlUCq1BlcjgmhRfAj3-Z8RY2VpuvV_tpd/root:",
|
||||
"id": "01BYE5RZ5MYLM2SMX75ZBIPQZIHT6OAYPB",
|
||||
"path": "/drive/root:/Business Data",
|
||||
"siteId": "d82312f9-b23b-4cbc-95d5-3e0d94e68c1e"
|
||||
},
|
||||
"file": {
|
||||
"mimeType": "image/jpeg",
|
||||
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"hashes": {
|
||||
"quickXorHash": "OGd+sgG4B/f1x6pn54GCsFTczzI="
|
||||
"quickXorHash": "r3UJbCEdsOVmLXQJQtBpJdUlXhA="
|
||||
}
|
||||
},
|
||||
"fileSystemInfo": {
|
||||
"createdDateTime": "2017-08-07T16:08:22Z",
|
||||
"lastModifiedDateTime": "2017-08-07T16:08:22Z"
|
||||
},
|
||||
"image": {
|
||||
"height": 183,
|
||||
"width": 260
|
||||
},
|
||||
"photo": {},
|
||||
"shared": {
|
||||
"scope": "users"
|
||||
"createdDateTime": "2017-08-07T16:17:09Z",
|
||||
"lastModifiedDateTime": "2017-08-07T16:17:09Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user