Use VCR for stubbing outbound HTTP requests (#13596)

https://community.openproject.org/work_packages/49797
This commit is contained in:
Kabiru Mwenja
2023-09-13 13:35:05 +03:00
committed by GitHub
parent a4a197cd75
commit 1075385e64
13 changed files with 563 additions and 101 deletions
+37
View File
@@ -0,0 +1,37 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 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.
#++
NEXTCLOUD_LOCAL_OAUTH_CLIENT_ID=
NEXTCLOUD_LOCAL_OAUTH_CLIENT_SECRET=
NEXTCLOUD_LOCAL_OPENPROJECT_UID=
NEXTCLOUD_LOCAL_OPENPROJECT_SECRET=
NEXTCLOUD_LOCAL_OPENPROJECT_REDIRECT_URI=https://nextcloud.local/index.php/apps/integration_openproject/oauth-redirect
NEXTCLOUD_LOCAL_OAUTH_CLIENT_ACCESS_TOKEN=
NEXTCLOUD_LOCAL_OAUTH_CLIENT_REFRESH_TOKEN=
+2
View File
@@ -251,6 +251,8 @@ group :test do
gem 'fuubar', '~> 2.5.0'
gem 'timecop', '~> 0.9.0'
# Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.
gem 'vcr'
# Mock backend requests (for ruby tests)
gem 'webmock', '~> 3.12', require: false
+2
View File
@@ -961,6 +961,7 @@ GEM
validate_url (1.0.15)
activemodel (>= 3.0.0)
public_suffix
vcr (6.2.0)
view_component (3.5.0)
activesupport (>= 5.2.0, < 8.0)
concurrent-ruby (~> 1.0)
@@ -1170,6 +1171,7 @@ DEPENDENCIES
typed_dag (~> 2.0.2)
tzinfo-data (~> 1.2023.1)
validate_url
vcr
view_component
warden (~> 1.2)
warden-basic_auth (~> 0.2.1)
@@ -13,6 +13,17 @@ services:
# It must be amended accordingly to OS.
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro
backend-test:
# Connect the backend-test container to the same network as the backend for nextcloud HTTP interactions
networks:
- external
volumes:
# Linux
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro
# Mac OS
# - ~/.step/certs:/etc/ssl/certs
# - ~/.step/certs:/usr/local/share/ca-certificates
frontend:
networks:
- external
@@ -47,11 +47,12 @@ module Storages::Peripherals::StorageInteraction::Nextcloud
service_result = begin
response = Util.http(@uri).post(
Util.join_uri_path(@uri.path, '/ocs/v2.php/apps/dav/api/v1/direct'),
{ fileId: file_link.origin_id },
{ fileId: file_link.origin_id }.to_json,
{
'Authorization' => "Bearer #{token.access_token}",
'OCS-APIRequest' => 'true',
'Accept' => 'application/json'
'Accept' => 'application/json',
'Content-Type' => 'application/json'
}
)
case response
@@ -31,23 +31,20 @@
require 'spec_helper'
require_module_spec_helper
RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::FilesInfoQuery, webmock: true do
RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::FilesInfoQuery,
:vcr, webmock: true do
using Storages::Peripherals::ServiceResultRefinements
let(:user) { create(:user) }
let(:url) { 'https://example.com' }
let(:origin_user_id) { 'admin' }
let(:storage) { build(:nextcloud_storage, :as_not_automatically_managed, host: url) }
let(:oauth_client) { create(:oauth_client, integration: storage) }
let(:token) { create(:oauth_client_token, origin_user_id:, access_token: 'xyz', oauth_client:, user:) }
before { token }
let(:storage) do
create(:nextcloud_storage_with_local_connection, :as_not_automatically_managed, oauth_client_token_user: user)
end
subject { described_class.new(storage) }
describe '#call' do
let(:file_ids) { %w[354 355] }
let(:file_ids) { %w[182 203 222] }
context 'without outbound request involved' do
context 'with an empty array of file ids' do
@@ -69,65 +66,8 @@ RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::FilesInfoQu
end
end
context 'with outbound request successful' do
let(:expected_response_body) do
<<~JSON
{
"ocs": {
"meta": {
"status": "ok",
"statuscode": 100,
"message": "OK",
"totalitems": "",
"itemsperpage": ""
},
"data": {
"354": {
"status": "OK",
"statuscode": 200,
"id": 354,
"name": "Demo project (1)",
"mtime": 1689162221,
"ctime": 0,
"mimetype": "application/x-op-directory",
"size": 989752,
"owner_name": "admin",
"owner_id": "admin",
"trashed": false,
"modifier_name": null,
"modifier_id": null,
"dav_permissions": "RMGDNVCK",
"path": "files/OpenProject/Demo project (1)"
},
"355": {
"status": "OK",
"statuscode": 200,
"id": 355,
"name": "minecraft.jpg",
"mtime": 1689162221,
"ctime": 0,
"mimetype": "image/jpeg",
"size": 989752,
"owner_name": "admin",
"owner_id": "admin",
"trashed": false,
"modifier_name": null,
"modifier_id": null,
"dav_permissions": "RMGDNVW",
"path": "files/OpenProject/Demo project (1)/minecraft.jpg"
}
}
}
}
JSON
end
before do
stub_request(:post, "https://example.com/ocs/v1.php/apps/integration_openproject/filesinfo")
.with(body: { fileIds: file_ids }.to_json)
.to_return(status: 200, body: expected_response_body)
end
context 'with outbound request successful',
vcr: 'nextcloud/files_info_query_success' do
context 'with an array of file ids' do
it 'must return an array of file information when called' do
result = subject.call(user:, file_ids:)
@@ -135,7 +75,7 @@ RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::FilesInfoQu
result.match(
on_success: ->(file_infos) do
expect(file_infos.size).to eq(2)
expect(file_infos.size).to eq(3)
expect(file_infos).to all(be_a(Storages::StorageFileInfo))
end,
on_failure: ->(error) { fail "Expected success, got #{error}" }
@@ -144,14 +84,16 @@ RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::FilesInfoQu
end
end
context 'with outbound request not authorized' do
before do
stub_request(:post, "https://example.com/ocs/v1.php/apps/integration_openproject/filesinfo")
.with(body: { fileIds: file_ids }.to_json)
.to_return(status: 401)
end
context 'with outbound request not authorized',
vcr: 'nextcloud/files_info_query_unauthorized' do
context 'with an array of file ids' do
before do
token = build_stubbed(:oauth_client_token, oauth_client: storage.oauth_client)
allow(Storages::Peripherals::StorageInteraction::Nextcloud::Util)
.to receive(:token)
.and_yield(token)
end
it 'must return an error when called' do
subject.call(user:, file_ids:).match(
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" },
@@ -162,17 +104,34 @@ RSpec.describe Storages::Peripherals::StorageInteraction::Nextcloud::FilesInfoQu
end
context 'with outbound request not found' do
before do
stub_request(:post, "https://example.com/ocs/v1.php/apps/integration_openproject/filesinfo")
.with(body: { fileIds: file_ids }.to_json)
.to_return(status: 404)
end
context 'with a single file id',
vcr: 'nextcloud/files_info_query_not_found' do
let(:file_ids) { %w[1234] }
context 'with an array of file ids' do
it 'must return an error when called' do
it 'returns an HTTP 200 with individual status code per file ID' do
subject.call(user:, file_ids:).match(
on_success: ->(file_infos) { fail "Expected failure, got #{file_infos}" },
on_failure: ->(error) { expect(error.code).to eq(:not_found) }
on_success: ->(file_infos) do
expect(file_infos.size).to eq(1)
expect(file_infos.first.to_h).to include(status: 'Not Found', status_code: 404)
end,
on_failure: ->(error) { fail "Expected success, got #{error}" }
)
end
end
end
context 'with outbound request not authorized' do
context 'with multiple file IDs, one of which is not authorized',
vcr: 'nextcloud/files_info_query_only_one_not_authorized' do
let(:file_ids) { %w[182 1234] }
it 'returns an HTTP 200 with individual status code per file ID' do
subject.call(user:, file_ids:).match(
on_success: ->(file_infos) do
expect(file_infos.size).to eq(2)
expect(file_infos.map(&:status_code)).to contain_exactly(403, 404)
end,
on_failure: ->(error) { fail "Expected success, got #{error}" }
)
end
end
@@ -39,23 +39,68 @@ FactoryBot.define do
oauth_client { build(:oauth_client) }
end
# rubocop:enable FactoryBot/FactoryAssociationWithStrategy
end
factory :one_drive_storage, class: "Storages::OneDriveStorage" do
host { nil }
factory :nextcloud_storage,
parent: :storage,
class: '::Storages::NextcloudStorage' do
provider_type { Storages::Storage::PROVIDER_TYPE_NEXTCLOUD }
sequence(:host) { |n| "https://host#{n}.example.com" }
trait :as_automatically_managed do
automatically_managed { true }
username { 'OpenProject' }
password { 'Password123' }
end
factory :nextcloud_storage, class: 'Storages::NextcloudStorage' do
sequence(:host) { |n| "https://host#{n}.example.com" }
trait :as_automatically_managed do
automatically_managed { true }
username { 'OpenProject' }
password { 'Password123' }
end
trait :as_not_automatically_managed do
automatically_managed { false }
end
trait :as_not_automatically_managed do
automatically_managed { false }
end
end
factory :nextcloud_storage_with_local_connection,
parent: :nextcloud_storage,
traits: [:as_not_automatically_managed] do
transient do
oauth_client_token_user { association :user }
end
name { 'Nextcloud Local' }
host { 'https://nextcloud.local' }
initialize_with do
Storages::NextcloudStorage.create_or_find_by(attributes.except(:oauth_client, :oauth_application))
end
after(:create) do |storage, evaluator|
create(:oauth_client,
client_id: ENV.fetch('NEXTCLOUD_LOCAL_OAUTH_CLIENT_ID', 'MISSING_NEXTCLOUD_LOCAL_OAUTH_CLIENT_ID'),
client_secret: ENV.fetch('NEXTCLOUD_LOCAL_OAUTH_CLIENT_SECRET', 'MISSING_NEXTCLOUD_LOCAL_OAUTH_CLIENT_SECRET'),
integration: storage)
create(:oauth_application,
uid: ENV.fetch('NEXTCLOUD_LOCAL_OPENPROJECT_UID', 'MISSING_NEXTCLOUD_LOCAL_OPENPROJECT_UID'),
secret: ENV.fetch('NEXTCLOUD_LOCAL_OPENPROJECT_SECRET', 'MISSING_NEXTCLOUD_LOCAL_OPENPROJECT_SECRET'),
redirect_uri: ENV.fetch('NEXTCLOUD_LOCAL_OPENPROJECT_REDIRECT_URI',
"https://nextcloud.local/index.php/apps/integration_openproject/oauth-redirect"),
scopes: 'api_v3',
integration: storage)
create(:oauth_client_token,
oauth_client: storage.oauth_client,
user: evaluator.oauth_client_token_user,
access_token: ENV.fetch('NEXTCLOUD_LOCAL_OAUTH_CLIENT_ACCESS_TOKEN',
'MISSING_NEXTCLOUD_LOCAL_OAUTH_CLIENT_ACCESS_TOKEN'),
refresh_token: ENV.fetch('NEXTCLOUD_LOCAL_OAUTH_CLIENT_REFRESH_TOKEN',
'MISSING_NEXTCLOUD_LOCAL_OAUTH_CLIENT_REFRESH_TOKEN'),
token_type: 'bearer',
origin_user_id: 'admin')
end
end
factory :one_drive_storage,
parent: :storage,
class: '::Storages::OneDriveStorage' do
host { nil }
end
end
+5
View File
@@ -36,6 +36,11 @@
require 'spec_helper'
require 'dry/container/stub'
# Record Storages Cassettes in module
VCR.configure do |config|
config.cassette_library_dir = 'modules/storages/spec/support/fixtures/vcr_cassettes'
end
# Loads files from relative support/ directory
Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
@@ -0,0 +1,88 @@
---
http_interactions:
- request:
method: post
uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/filesinfo
body:
encoding: UTF-8
string: '{"fileIds":["1234"]}'
headers:
Authorization:
- Bearer L49hIQGzShBYfjblMAtTDtT15rtZ8wagxFIbwQTzD0LRIfUOBmOYz9wY5pvIY9zkLMpXLcK9
Accept:
- application/json
Content-Type:
- application/json
Ocs-Apirequest:
- 'true'
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Access-Control-Allow-Credentials:
- 'true'
Cache-Control:
- no-cache, no-store, must-revalidate
Content-Length:
- '154'
Content-Security-Policy:
- default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 30 Aug 2023 15:26:14 GMT
Expires:
- Thu, 19 Nov 1981 08:52:00 GMT
Feature-Policy:
- autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone
'none';payment 'none'
Pragma:
- no-cache
Referrer-Policy:
- no-referrer
Server:
- Apache/2.4.56 (Debian)
Set-Cookie:
- __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100
23:59:59 GMT; SameSite=lax
- __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri,
31-Dec-2100 23:59:59 GMT; SameSite=strict
- oc_sessionPassphrase=mubP6L1KhzkAbwW%2BdVOdSsS10ZEeOJUYFAEVeqbp1%2BA37vA9h98ve5%2BxUBz1zPeIpCJRBNvPfF1sOmZBn5HM8qGFwvc9b9scbO4E9GovlEPYW0X%2B1WMN0eKqmW45nR7A;
path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=cc97b31ff8dede5d34607ee68aff20e8; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=ff3381b14b648bcb48e62a82cbb42c87; path=/; secure; HttpOnly; SameSite=Lax
Vary:
- Origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Powered-By:
- PHP/8.2.8
X-Request-Id:
- v3tT2TMs2xjqxJOvWJ2f
X-Robots-Tag:
- noindex, nofollow
X-Xss-Protection:
- 1; mode=block
body:
encoding: UTF-8
string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"1234":{"status":"Not
Found","statuscode":404}}}}'
recorded_at: Wed, 30 Aug 2023 15:26:14 GMT
recorded_with: VCR 6.2.0
@@ -0,0 +1,88 @@
---
http_interactions:
- request:
method: post
uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/filesinfo
body:
encoding: UTF-8
string: '{"fileIds":["182","1234"]}'
headers:
Authorization:
- Bearer L49hIQGzShBYfjblMAtTDtT15rtZ8wagxFIbwQTzD0LRIfUOBmOYz9wY5pvIY9zkLMpXLcK9
Accept:
- application/json
Content-Type:
- application/json
Ocs-Apirequest:
- 'true'
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Access-Control-Allow-Credentials:
- 'true'
Cache-Control:
- no-cache, no-store, must-revalidate
Content-Length:
- '200'
Content-Security-Policy:
- default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 30 Aug 2023 15:42:44 GMT
Expires:
- Thu, 19 Nov 1981 08:52:00 GMT
Feature-Policy:
- autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone
'none';payment 'none'
Pragma:
- no-cache
Referrer-Policy:
- no-referrer
Server:
- Apache/2.4.56 (Debian)
Set-Cookie:
- __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100
23:59:59 GMT; SameSite=lax
- __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri,
31-Dec-2100 23:59:59 GMT; SameSite=strict
- oc_sessionPassphrase=jrT6r0yM%2BFS1HHed4hww77b%2B4Nv2Sf1UYogAKMFI2xarG0FxxSDQcuuwf%2FhVigK4HNXAOjdtVY%2BcAZJvM3KyVy%2FZIVkiIH7C3CR%2FQEFybCQPE2ecRh9dnS6UkGX7nz1R;
path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=2097f255d8b54122037144f5504cd33e; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=69f515e7c5bfb387de23f92cf0bbebcc; path=/; secure; HttpOnly; SameSite=Lax
Vary:
- Origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Powered-By:
- PHP/8.2.8
X-Request-Id:
- RqDl34ieFVXiEvFcPeJV
X-Robots-Tag:
- noindex, nofollow
X-Xss-Protection:
- 1; mode=block
body:
encoding: UTF-8
string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"182":{"status":"Forbidden","statuscode":403},"1234":{"status":"Not
Found","statuscode":404}}}}'
recorded_at: Wed, 30 Aug 2023 15:42:45 GMT
recorded_with: VCR 6.2.0
@@ -0,0 +1,89 @@
---
http_interactions:
- request:
method: post
uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/filesinfo
body:
encoding: UTF-8
string: '{"fileIds":["182","203","222"]}'
headers:
Authorization:
- Bearer L49hIQGzShBYfjblMAtTDtT15rtZ8wagxFIbwQTzD0LRIfUOBmOYz9wY5pvIY9zkLMpXLcK9
Accept:
- application/json
Content-Type:
- application/json
Ocs-Apirequest:
- 'true'
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- Ruby
response:
status:
code: 200
message: OK
headers:
Access-Control-Allow-Credentials:
- 'true'
Cache-Control:
- no-cache, no-store, must-revalidate
Content-Length:
- '577'
Content-Security-Policy:
- default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Content-Type:
- application/json; charset=utf-8
Date:
- Wed, 30 Aug 2023 15:45:26 GMT
Expires:
- Thu, 19 Nov 1981 08:52:00 GMT
Feature-Policy:
- autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone
'none';payment 'none'
Pragma:
- no-cache
Referrer-Policy:
- no-referrer
Server:
- Apache/2.4.56 (Debian)
Set-Cookie:
- __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100
23:59:59 GMT; SameSite=lax
- __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri,
31-Dec-2100 23:59:59 GMT; SameSite=strict
- oc_sessionPassphrase=bZysxrG%2Fl16DjX2dkVG88Pgrm1tYYZ7EzUwAVCaBnEnVxo8pbldMJx2U9QF%2FXm%2Blyz8WZSNH10txYYv%2BXIBIOhZQCpNue%2BiOgD4BTSq%2BBL4VlFQ4OEnyKTMeCwrk1vr%2F;
path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=57a237ced5d8cbea7fa030db90ed0f3f; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=e4353119162ec0f0020b925c614ce423; path=/; secure; HttpOnly; SameSite=Lax
Vary:
- Origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Powered-By:
- PHP/8.2.8
X-Request-Id:
- Oi4F9CkhBWYYmLeEmoUp
X-Robots-Tag:
- noindex, nofollow
X-Xss-Protection:
- 1; mode=block
body:
encoding: UTF-8
string: '{"ocs":{"meta":{"status":"ok","statuscode":100,"message":"OK","totalitems":"","itemsperpage":""},"data":{"182":{"status":"Forbidden","statuscode":403},"203":{"status":"Forbidden","statuscode":403},"222":{"status":"OK","statuscode":200,"id":222,"name":"Screenshot
2023-08-15 at 3.00.54 PM.jpg","mtime":1692187580,"ctime":0,"mimetype":"image\/jpeg","size":81944,"owner_name":"member","owner_id":"member","trashed":false,"modifier_name":null,"modifier_id":null,"dav_permissions":"RMGDNVW","path":"files\/OpenProject\/Scrum
project (2)\/Screenshot 2023-08-15 at 3.00.54 PM.jpg"}}}}'
recorded_at: Wed, 30 Aug 2023 15:45:26 GMT
recorded_with: VCR 6.2.0
@@ -0,0 +1,82 @@
---
http_interactions:
- request:
method: post
uri: https://nextcloud.local/ocs/v1.php/apps/integration_openproject/filesinfo
body:
encoding: UTF-8
string: '{"fileIds":["182","203","222"]}'
headers:
Authorization:
- Bearer 1234567890-1
Accept:
- application/json
Content-Type:
- application/json
Ocs-Apirequest:
- 'true'
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- Ruby
response:
status:
code: 401
message: Unauthorized
headers:
Access-Control-Allow-Credentials:
- 'true'
Cache-Control:
- no-cache, no-store, must-revalidate
Content-Length:
- '140'
Content-Security-Policy:
- default-src 'none';base-uri 'none';manifest-src 'self';frame-ancestors 'none'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 31 Aug 2023 15:56:02 GMT
Expires:
- Thu, 19 Nov 1981 08:52:00 GMT
Feature-Policy:
- autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone
'none';payment 'none'
Pragma:
- no-cache
Referrer-Policy:
- no-referrer
Server:
- Apache/2.4.56 (Debian)
Set-Cookie:
- __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100
23:59:59 GMT; SameSite=lax
- __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri,
31-Dec-2100 23:59:59 GMT; SameSite=strict
- oc_sessionPassphrase=jerIWxh2u207KZvn8P9QfqUQqhxH1PU9dwZGLgmFmmE7YvuUvHLkMAXQJ6cxw0Tv622PCSD3z4wvuv%2BQZYmocMUcRJxkjuSMaUrwXB83Ys2%2BO%2BegSfLT12NgAQPSGY82;
path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=40ab489740e67cfe180e2c0fce9972a4; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=8e5f3e155930f7d2a03ce41bb8c67e49; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=8e5f3e155930f7d2a03ce41bb8c67e49; path=/; secure; HttpOnly; SameSite=Lax
- ocybhqi440sc=8e5f3e155930f7d2a03ce41bb8c67e49; path=/; secure; HttpOnly; SameSite=Lax
Vary:
- Origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Powered-By:
- PHP/8.2.8
X-Request-Id:
- HbnpSYoZ0evEYxmtZRPO
X-Robots-Tag:
- noindex, nofollow
X-Xss-Protection:
- 1; mode=block
body:
encoding: UTF-8
string: '{"ocs":{"meta":{"status":"failure","statuscode":997,"message":"Current
user is not logged in","totalitems":"","itemsperpage":""},"data":[]}}'
recorded_at: Thu, 31 Aug 2023 15:56:02 GMT
recorded_with: VCR 6.2.0
+53
View File
@@ -0,0 +1,53 @@
#-- 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 'vcr'
VCR.configure do |config|
config.cassette_library_dir = 'spec/support/fixtures/vcr_cassettes'
config.hook_into :webmock
config.configure_rspec_metadata!
config.before_record do |i|
i.response.body.force_encoding('UTF-8')
end
end
VCR.turn_off!
RSpec.configure do |config|
config.around(:example, :vcr) do |example|
# Only enable VCR's webmock integration for tests tagged with :vcr otherwise interferes with WebMock
# See: https://github.com/vcr/vcr/issues/146
#
VCR.turn_on!
example.run
ensure
# Switch off VCR to prevent VCR from interfering with other tests
VCR.turn_off!
end
end