mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
FeatureDecision for Sharepoint and Renaming of namespaces (#19953)
* Adds FeatureDecision. Initial steps on SharePoint -> Sharepoint rename * Update I18n keys to use sharepoint over share_point * Adds handling of the drives on the file picker * Upload Strategy handling plus FileLink Contract ammendment
This commit is contained in:
@@ -49,11 +49,11 @@ ONE_DRIVE_TEST_OAUTH_CLIENT_SECRET=
|
||||
ONE_DRIVE_TEST_OAUTH_CLIENT_ACCESS_TOKEN=
|
||||
ONE_DRIVE_TEST_OAUTH_CLIENT_REFRESH_TOKEN=
|
||||
|
||||
SHARE_POINT_TEST_HOST=
|
||||
SHARE_POINT_TEST_TENANT_ID=
|
||||
SHAREPOINT_TEST_HOST=
|
||||
SHAREPOINT_TEST_TENANT_ID=
|
||||
|
||||
SHARE_POINT_TEST_OAUTH_CLIENT_ID=
|
||||
SHARE_POINT_TEST_OAUTH_CLIENT_SECRET=
|
||||
SHAREPOINT_TEST_OAUTH_CLIENT_ID=
|
||||
SHAREPOINT_TEST_OAUTH_CLIENT_SECRET=
|
||||
|
||||
SHARE_POINT_TEST_OAUTH_CLIENT_ACCESS_TOKEN=
|
||||
SHARE_POINT_TEST_OAUTH_CLIENT_REFRESH_TOKEN=
|
||||
SHAREPOINT_TEST_OAUTH_CLIENT_ACCESS_TOKEN=
|
||||
SHAREPOINT_TEST_OAUTH_CLIENT_REFRESH_TOKEN=
|
||||
|
||||
+11
-5
@@ -46,7 +46,7 @@ import { FileLinksResourceService } from 'core-app/core/state/file-links/file-li
|
||||
import { isDirectory, storageLocaleString } from 'core-app/shared/components/storages/functions/storages.functions';
|
||||
import { StorageFilesResourceService } from 'core-app/core/state/storage-files/storage-files.service';
|
||||
import {
|
||||
StorageFileListItem,
|
||||
StorageFileListItem, StorageFileListItemCheckbox,
|
||||
} from 'core-app/shared/components/storages/storage-file-list-item/storage-file-list-item';
|
||||
import {
|
||||
FilePickerBaseModalComponent,
|
||||
@@ -192,13 +192,19 @@ export class FilePickerModalComponent extends FilePickerBaseModalComponent {
|
||||
this.enterDirectoryCallback(file),
|
||||
false,
|
||||
this.tooltip(file),
|
||||
{
|
||||
selected: this.selection.has(file.id as string),
|
||||
changeSelection: () => { this.changeSelection(file); },
|
||||
},
|
||||
this.hasCheckbox(file),
|
||||
);
|
||||
}
|
||||
|
||||
private hasCheckbox(file:IStorageFile):StorageFileListItemCheckbox|undefined {
|
||||
if (file.mimeType !== 'application/x-op-drive') {
|
||||
return {
|
||||
selected: this.selection.has(file.id as string),
|
||||
changeSelection: () => { this.changeSelection(file); }
|
||||
};
|
||||
} else { return; }
|
||||
}
|
||||
|
||||
private isAlreadyLinked(file:IStorageFile):boolean {
|
||||
const currentFileLinks = this.locals.fileLinks as IFileLink[];
|
||||
const found = currentFileLinks.find((a) => a.originData.id === file.id);
|
||||
|
||||
@@ -33,10 +33,14 @@ import {
|
||||
} from 'core-app/shared/components/storages/icons.mapping';
|
||||
import { IHalResourceLink } from 'core-app/core/state/hal-resource';
|
||||
import { IFileLinkOriginData } from 'core-app/core/state/file-links/file-link.model';
|
||||
import { nextcloud, oneDrive } from 'core-app/shared/components/storages/storages-constants.const';
|
||||
import { nextcloud, oneDrive, sharepoint } from 'core-app/shared/components/storages/storages-constants.const';
|
||||
|
||||
export function isDirectory(originData:IFileLinkOriginData):boolean {
|
||||
return originData.mimeType === 'application/x-op-directory';
|
||||
return originData.mimeType === 'application/x-op-directory' || isDrive(originData);
|
||||
}
|
||||
|
||||
function isDrive(originData:IFileLinkOriginData):boolean {
|
||||
return originData.mimeType === 'application/x-op-drive';
|
||||
}
|
||||
|
||||
export function getIconForMimeType(mimeType?:string):IFileIcon {
|
||||
@@ -67,6 +71,7 @@ export function makeFilesCollectionLink(storageLink:IHalResourceLink, location:s
|
||||
const storageTypeMap:Record<string, string> = {
|
||||
[nextcloud]: 'js.storages.types.nextcloud',
|
||||
[oneDrive]: 'js.storages.types.one_drive',
|
||||
[sharepoint]: 'js.storages.types.sharepoint',
|
||||
default: 'js.storages.types.default',
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import { nextcloud } from 'core-app/shared/components/storages/storages-constants.const';
|
||||
|
||||
export interface IFileIcon {
|
||||
icon:'image1'|'movie'|'file-text'|'export-pdf-descr'|'file-doc'|'file-sheet'|'file-presentation'|'folder'|'ticket'
|
||||
icon:'image1'|'movie'|'file-text'|'export-pdf-descr'|'file-doc'|'file-sheet'|'file-presentation'|'folder'|'ticket'|'inbox'
|
||||
clazz:'pdf'|'img'|'txt'|'doc'|'sheet'|'presentation'|'form'|'primary'|'mov'|'default'
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ export const fileIconMappings:Record<string, IFileIcon> = {
|
||||
'video/3gpp-2': { icon: 'movie', clazz: 'mov' },
|
||||
|
||||
'application/x-op-directory': { icon: 'folder', clazz: 'primary' },
|
||||
'application/x-op-drive': { icon: 'inbox', clazz: 'primary' },
|
||||
|
||||
default: { icon: 'ticket', clazz: 'default' },
|
||||
};
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ import { TimezoneService } from 'core-app/core/datetime/timezone.service';
|
||||
import { IFileIcon } from 'core-app/shared/components/storages/icons.mapping';
|
||||
import { getIconForMimeType, isDirectory } from 'core-app/shared/components/storages/functions/storages.functions';
|
||||
|
||||
interface StorageFileListItemCheckbox {
|
||||
export interface StorageFileListItemCheckbox {
|
||||
selected:boolean;
|
||||
changeSelection?:() => void;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Storage types
|
||||
export const nextcloud = 'urn:openproject-org:api:v3:storages:Nextcloud';
|
||||
export const oneDrive = 'urn:openproject-org:api:v3:storages:OneDrive';
|
||||
export const sharepoint = 'urn:openproject-org:api:v3:storages:Sharepoint';
|
||||
|
||||
// Storage authorization state
|
||||
export const storageConnected = 'urn:openproject-org:api:v3:storages:authorization:Connected';
|
||||
|
||||
@@ -34,7 +34,7 @@ import { HttpClient, HttpEvent } from '@angular/common/http';
|
||||
import { IUploadFile, OpUploadService } from 'core-app/core/upload/upload.service';
|
||||
import { IUploadStrategy } from 'core-app/shared/components/storages/upload/upload-strategy';
|
||||
import { NextcloudUploadStrategy } from 'core-app/shared/components/storages/upload/nextcloud-upload.strategy';
|
||||
import { nextcloud, oneDrive } from 'core-app/shared/components/storages/storages-constants.const';
|
||||
import { nextcloud, oneDrive, sharepoint } from 'core-app/shared/components/storages/storages-constants.const';
|
||||
import { OneDriveUploadStrategy } from 'core-app/shared/components/storages/upload/one-drive-upload.strategy';
|
||||
|
||||
export interface IStorageFileUploadResponse {
|
||||
@@ -73,6 +73,9 @@ export class StorageUploadService extends OpUploadService {
|
||||
case oneDrive:
|
||||
this.uploadStrategy = new OneDriveUploadStrategy(this.http);
|
||||
break;
|
||||
case sharepoint:
|
||||
this.uploadStrategy = new OneDriveUploadStrategy(this.http);
|
||||
break;
|
||||
default:
|
||||
throw new Error('unknown storage type');
|
||||
}
|
||||
|
||||
+4
-4
@@ -31,12 +31,12 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
class Base
|
||||
include TaggedLogging
|
||||
include Dry::Monads::Result(Results::Error)
|
||||
|
||||
# @param storage [Storages::SharePointStorage]
|
||||
# @param storage [Storages::SharepointStorage]
|
||||
# @param auth_strategy [Result(Input::Strategy)]
|
||||
# @param input_data [Data]
|
||||
# @return [Success, Failure(Results::Error)]
|
||||
@@ -44,7 +44,7 @@ module Storages
|
||||
new(storage).call(auth_strategy:, input_data:)
|
||||
end
|
||||
|
||||
# @param storage [Storages::SharePointStorage]
|
||||
# @param storage [Storages::SharepointStorage]
|
||||
def initialize(storage)
|
||||
@storage = storage
|
||||
end
|
||||
@@ -66,7 +66,7 @@ module Storages
|
||||
end
|
||||
|
||||
def split_identifier(location)
|
||||
drive_id, item_id = location.to_s.split(SharePointStorage::IDENTIFIER_SEPARATOR)
|
||||
drive_id, item_id = location.to_s.split(SharepointStorage::IDENTIFIER_SEPARATOR)
|
||||
{ drive_id:, location: Peripherals::ParentFolder.new(item_id || "/") }
|
||||
end
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Commands
|
||||
class CreateFolderCommand < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Commands
|
||||
class DeleteFolderCommand < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
OAuthConfiguration = Providers::OneDrive::OAuthConfiguration
|
||||
end
|
||||
end
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class DownloadLinkQuery < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+2
-2
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class FileInfoQuery < Base
|
||||
FIELDS = %w[id name fileSystemInfo file folder size createdBy lastModifiedBy parentReference webUrl].freeze
|
||||
@@ -70,7 +70,7 @@ module Storages
|
||||
end
|
||||
end
|
||||
|
||||
def userless_strategy = Registry.resolve("share_point.authentication.userless").call
|
||||
def userless_strategy = Registry.resolve("#{@storage}.authentication.userless").call
|
||||
|
||||
def storage_file_info(json, status: "ok", status_code: 200)
|
||||
StorageFileTransformer.new(site_name).transform_file_info({ status:, status_code: }.merge(json))
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class FilesInfoQuery < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class FilesQuery < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
module Internal
|
||||
class ChildrenQuery < Base
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
module Internal
|
||||
class DriveItemQuery < Base
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
module Internal
|
||||
class ListsQuery < Base
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class OpenFileLinkQuery < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class OpenStorageQuery < Base
|
||||
def call(**)
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
class UploadLinkQuery < Base
|
||||
def call(auth_strategy:, input_data:)
|
||||
+2
-2
@@ -31,8 +31,8 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
class SharePointContract < ::ModelContract
|
||||
module Sharepoint
|
||||
class SharepointContract < ::ModelContract
|
||||
attribute :name
|
||||
validates :name, presence: true, length: { maximum: 255 }
|
||||
|
||||
+4
-4
@@ -31,8 +31,8 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
SharePointRegistry = Dry::Container::Namespace.new("share_point") do
|
||||
module Sharepoint
|
||||
SharepointRegistry = Dry::Container::Namespace.new("sharepoint") do
|
||||
namespace("authentication") do
|
||||
register(:userless, ->(use_cache = true) { Input::Strategy.build(key: :oauth_client_credentials, use_cache:) })
|
||||
register(:user_bound, ->(user, storage = nil) { Input::Strategy.build(key: :oauth_user_token, user:, storage:) })
|
||||
@@ -60,8 +60,8 @@ module Storages
|
||||
end
|
||||
|
||||
namespace("contracts") do
|
||||
register(:storage, SharePointContract)
|
||||
register(:general_information, SharePointContract)
|
||||
register(:storage, SharepointContract)
|
||||
register(:general_information, SharepointContract)
|
||||
end
|
||||
|
||||
namespace("validators") do
|
||||
+3
-3
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
class StorageFileTransformer
|
||||
attr_reader :site_name
|
||||
|
||||
@@ -112,13 +112,13 @@ module Storages
|
||||
end
|
||||
|
||||
def compose_id(json)
|
||||
"#{json.dig(:parentReference, :driveId)}#{SharePointStorage::IDENTIFIER_SEPARATOR}#{json[:id]}"
|
||||
"#{json.dig(:parentReference, :driveId)}#{SharepointStorage::IDENTIFIER_SEPARATOR}#{json[:id]}"
|
||||
end
|
||||
|
||||
def compose_parent_id(parent)
|
||||
item_id = parent[:path].ends_with?("root:") ? nil : parent[:id]
|
||||
|
||||
"#{parent[:driveId]}#{SharePointStorage::IDENTIFIER_SEPARATOR}#{item_id}"
|
||||
"#{parent[:driveId]}#{SharepointStorage::IDENTIFIER_SEPARATOR}#{item_id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
class StorageWizard < Wizard
|
||||
step :general_information, completed_if: ->(storage) { storage.name.present? }
|
||||
|
||||
+3
-3
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Validators
|
||||
class AuthenticationValidator < ConnectionValidators::BaseValidatorGroup
|
||||
def self.key = :authentication
|
||||
@@ -58,13 +58,13 @@ module Storages
|
||||
end
|
||||
|
||||
def user_bound_request
|
||||
Registry["share_point.queries.user"].call(storage: @storage, auth_strategy:).either(
|
||||
Registry["sharepoint.queries.user"].call(storage: @storage, auth_strategy:).either(
|
||||
->(_) { pass_check(:user_bound_request) },
|
||||
-> { fail_check(:user_bound_request, :"sp_oauth_request_#{it.code}") }
|
||||
)
|
||||
end
|
||||
|
||||
def auth_strategy = Registry["share_point.authentication.user_bound"].call(@user, @storage)
|
||||
def auth_strategy = Registry["sharepoint.authentication.user_bound"].call(@user, @storage)
|
||||
end
|
||||
end
|
||||
end
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Validators
|
||||
class ConnectionValidator < ConnectionValidators::BaseConnectionValidator
|
||||
register_group StorageConfigurationValidator
|
||||
+2
-2
@@ -31,7 +31,7 @@
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Validators
|
||||
class StorageConfigurationValidator < ConnectionValidators::BaseValidatorGroup
|
||||
def self.key = :base_configuration
|
||||
@@ -121,7 +121,7 @@ module Storages
|
||||
end
|
||||
end
|
||||
|
||||
def auth_strategy = Registry["share_point.authentication.userless"].call
|
||||
def auth_strategy = Registry["sharepoint.authentication.userless"].call
|
||||
|
||||
def error_payload
|
||||
@error_payload ||= query_result.either(->(_) { {} }, -> { MultiJson.load(it.payload, symbolize_keys: true) })
|
||||
@@ -62,7 +62,7 @@ module Storages
|
||||
# Need to make this dynamic to ease new providers to be registered
|
||||
import Providers::Nextcloud::NextcloudRegistry
|
||||
import Providers::OneDrive::OneDriveRegistry
|
||||
import Providers::SharePoint::SharePointRegistry
|
||||
import Providers::Sharepoint::SharepointRegistry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,7 +36,6 @@ class Storages::FileLinks::CreateContract < ModelContract
|
||||
attribute :container_type
|
||||
|
||||
attribute :origin_id
|
||||
validates :origin_id, length: 1..100
|
||||
attribute :origin_name
|
||||
validates :origin_name, presence: true
|
||||
attribute :origin_created_by_name
|
||||
|
||||
+10
-5
@@ -29,8 +29,8 @@
|
||||
#++
|
||||
|
||||
module Storages
|
||||
class SharePointStorage < Storage
|
||||
IDENTIFIER_SEPARATOR = "||"
|
||||
class SharepointStorage < Storage
|
||||
IDENTIFIER_SEPARATOR = ":"
|
||||
|
||||
PROVIDER_FIELDS_DEFAULTS = {
|
||||
automatically_managed: false,
|
||||
@@ -42,10 +42,10 @@ module Storages
|
||||
# For now SharePoint is visible only in tests.
|
||||
# This is to prevent it from being shown in the UI, as it is not ready yet.
|
||||
def self.visible?
|
||||
Rails.env.local?
|
||||
OpenProject::FeatureDecisions.sharepoint_storage_active? || Rails.env.local?
|
||||
end
|
||||
|
||||
def self.short_provider_name = :share_point
|
||||
def self.short_provider_name = :sharepoint
|
||||
|
||||
def self.non_confidential_provider_fields
|
||||
super + %i[tenant_id]
|
||||
@@ -69,7 +69,12 @@ module Storages
|
||||
@uri ||= URI("https://graph.microsoft.com").normalize
|
||||
end
|
||||
|
||||
def oauth_configuration = Adapters::Providers::SharePoint::OAuthConfiguration.new(self)
|
||||
def connect_src
|
||||
host_uri = URI(host)
|
||||
["#{host_uri.scheme}://#{host_uri.host}"]
|
||||
end
|
||||
|
||||
def oauth_configuration = Adapters::Providers::Sharepoint::OAuthConfiguration.new(self)
|
||||
|
||||
def provider_fields_defaults
|
||||
PROVIDER_FIELDS_DEFAULTS
|
||||
@@ -199,7 +199,7 @@ module Storages
|
||||
end
|
||||
|
||||
def provider_type_share_point?
|
||||
is_a?(SharePointStorage)
|
||||
is_a?(SharepointStorage)
|
||||
end
|
||||
|
||||
def health_reason_identifier
|
||||
|
||||
@@ -22,7 +22,7 @@ en:
|
||||
project_folder_mode: Project folder mode
|
||||
storage: Storage
|
||||
storage_url: Storage URL
|
||||
storages/share_point_storage:
|
||||
storages/sharepoint_storage:
|
||||
host: Sharepoint Site URL
|
||||
library: Library ID
|
||||
name: Name
|
||||
@@ -196,10 +196,10 @@ en:
|
||||
oauth_client_incomplete:
|
||||
nextcloud: Allow OpenProject to access Nextcloud data using OAuth.
|
||||
one_drive: Allow OpenProject to access Azure data using OAuth to connect OneDrive.
|
||||
share_point: Allow OpenProject to access SharePoint data using OAuth.
|
||||
sharepoint: Allow OpenProject to access SharePoint data using OAuth.
|
||||
redirect_uri_incomplete:
|
||||
one_drive: Complete the setup with the correct URI redirection.
|
||||
share_point: Complete the setup with the correct URI redirection.
|
||||
sharepoint: Complete the setup with the correct URI redirection.
|
||||
confirm_replace_oauth_application: This action will reset the current OAuth credentials. After confirming you will have to reenter the credentials at the storage provider and all remote users will have to authorize against OpenProject again. Are you sure you want to proceed?
|
||||
confirm_replace_oauth_client: This action will reset the current OAuth credentials. After confirming you will have to enter new credentials from the storage provider and all users will have to authorize against %{provider_type} again. Are you sure you want to proceed?
|
||||
delete_warning:
|
||||
@@ -396,7 +396,7 @@ en:
|
||||
setting_up_additional_storages_non_admin: Administrators can set up additional file storages in Administration / File storages.
|
||||
setting_up_storages: For setting up file storages, please visit
|
||||
setting_up_storages_non_admin: Administrators can set up file storages in Administration / File storages.
|
||||
share_point:
|
||||
sharepoint:
|
||||
application_link_text: SharePoint site
|
||||
integration: SharePoint Administration / OpenProject
|
||||
oauth_configuration: Copy these values from the desired application in the %{application_link_text}.
|
||||
@@ -502,7 +502,7 @@ en:
|
||||
label_oauth_client_secret: Azure OAuth Client Secret Value
|
||||
name: OneDrive
|
||||
name_placeholder: e.g. OneDrive
|
||||
share_point:
|
||||
sharepoint:
|
||||
label_oauth_client_id: Azure OAuth Application (client) ID
|
||||
label_oauth_client_secret: Azure OAuth Client Secret Value
|
||||
name: SharePoint
|
||||
|
||||
@@ -18,7 +18,8 @@ en:
|
||||
|
||||
types:
|
||||
nextcloud: "Nextcloud"
|
||||
one_drive: "OneDrive/SharePoint"
|
||||
one_drive: "OneDrive"
|
||||
sharepoint: "SharePoint"
|
||||
default: "Storage"
|
||||
|
||||
information:
|
||||
|
||||
@@ -40,12 +40,12 @@ module API::V3::Storages
|
||||
|
||||
URN_STORAGE_TYPE_NEXTCLOUD = "#{::API::V3::URN_PREFIX}storages:Nextcloud".freeze
|
||||
URN_STORAGE_TYPE_ONE_DRIVE = "#{::API::V3::URN_PREFIX}storages:OneDrive".freeze
|
||||
URN_STORAGE_TYPE_SHARE_POINT = "#{::API::V3::URN_PREFIX}storages:SharePoint".freeze
|
||||
URN_STORAGE_TYPE_SHARE_POINT = "#{::API::V3::URN_PREFIX}storages:Sharepoint".freeze
|
||||
|
||||
STORAGE_TYPE_MAP = {
|
||||
URN_STORAGE_TYPE_NEXTCLOUD => Storages::NextcloudStorage.name,
|
||||
URN_STORAGE_TYPE_ONE_DRIVE => Storages::OneDriveStorage.name,
|
||||
URN_STORAGE_TYPE_SHARE_POINT => Storages::SharePointStorage.name
|
||||
URN_STORAGE_TYPE_SHARE_POINT => Storages::SharepointStorage.name
|
||||
}.freeze
|
||||
|
||||
STORAGE_TYPE_URN_MAP = STORAGE_TYPE_MAP.invert.freeze
|
||||
|
||||
@@ -52,6 +52,7 @@ module OpenProject::Storages
|
||||
|
||||
initializer "openproject_storages.feature_decisions" do
|
||||
OpenProject::FeatureDecisions.add :storage_file_picking_select_all
|
||||
OpenProject::FeatureDecisions.add :sharepoint_storage
|
||||
end
|
||||
|
||||
initializer "openproject_storages.event_subscriptions" do
|
||||
@@ -261,7 +262,7 @@ module OpenProject::Storages
|
||||
Storages::Storage::InexistentStorage
|
||||
Storages::OneDriveStorage
|
||||
Storages::NextcloudStorage
|
||||
Storages::SharePointStorage
|
||||
Storages::SharepointStorage
|
||||
|
||||
# Allow the browser to connect to external servers for direct file uploads.
|
||||
AppendStoragesHostsToCspHook
|
||||
|
||||
+10
-10
@@ -34,17 +34,17 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Commands
|
||||
RSpec.describe CreateFolderCommand, :webmock do
|
||||
let(:storage) { create(:share_point_storage, :sandbox) }
|
||||
let(:auth_strategy) { Registry.resolve("share_point.authentication.userless").call(false) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox) }
|
||||
let(:auth_strategy) { Registry.resolve("sharepoint.authentication.userless").call(false) }
|
||||
let(:base_drive) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW" }
|
||||
let(:input_data) { Input::CreateFolder.build(folder_name:, parent_location:).value! }
|
||||
|
||||
it_behaves_like "adapter create_folder_command: basic command setup"
|
||||
|
||||
context "when creating a folder in the root", vcr: "share_point/create_folder_root" do
|
||||
context "when creating a folder in the root", vcr: "sharepoint/create_folder_root" do
|
||||
let(:folder_name) { "Földer CreatedBy Çommand" }
|
||||
let(:parent_location) { composite_identifier(nil) }
|
||||
let(:path) { "/Marcello%20VCR/F%C3%B6lder%20CreatedBy%20%C3%87ommand" }
|
||||
@@ -52,7 +52,7 @@ module Storages
|
||||
it_behaves_like "adapter create_folder_command: successful folder creation"
|
||||
end
|
||||
|
||||
context "when creating a folder in a parent folder", vcr: "share_point/create_folder_parent" do
|
||||
context "when creating a folder in a parent folder", vcr: "sharepoint/create_folder_parent" do
|
||||
let(:folder_name) { "Földer CreatedBy Çommand" }
|
||||
let(:parent_location) { composite_identifier("01ANJ53W7TITEF4WCHRBDKR7VMNUWZ33WD") }
|
||||
let(:path) { "/Marcello%20VCR/Folder%20with%20spaces/F%C3%B6lder%20CreatedBy%20%C3%87ommand" }
|
||||
@@ -60,14 +60,14 @@ module Storages
|
||||
it_behaves_like "adapter create_folder_command: successful folder creation"
|
||||
end
|
||||
|
||||
context "when creating a folder in a non-existing parent folder", vcr: "share_point/create_folder_parent_not_found" do
|
||||
context "when creating a folder in a non-existing parent folder", vcr: "sharepoint/create_folder_parent_not_found" do
|
||||
let(:folder_name) { "Földer CreatedBy Çommand" }
|
||||
let(:parent_location) { composite_identifier("01AZJL5PKU2WV3U3RKKFF4A7ZCWVBXRTEU") }
|
||||
|
||||
it_behaves_like "adapter create_folder_command: parent not found"
|
||||
end
|
||||
|
||||
context "when folder already exists", vcr: "share_point/create_folder_already_exists" do
|
||||
context "when folder already exists", vcr: "sharepoint/create_folder_already_exists" do
|
||||
let(:folder_name) { "data" }
|
||||
let(:parent_location) { composite_identifier(nil) }
|
||||
|
||||
@@ -75,7 +75,7 @@ module Storages
|
||||
end
|
||||
|
||||
context "when trying to create a folder under the root of the site",
|
||||
vcr: "share_point/create_folder_invalid_request" do
|
||||
vcr: "sharepoint/create_folder_invalid_request" do
|
||||
let(:folder_name) { "cant_do_that_folder" }
|
||||
let(:parent_location) { "/" }
|
||||
|
||||
@@ -92,11 +92,11 @@ module Storages
|
||||
|
||||
private
|
||||
|
||||
def composite_identifier(item_id) = "#{base_drive}#{SharePointStorage::IDENTIFIER_SEPARATOR}#{item_id}"
|
||||
def composite_identifier(item_id) = "#{base_drive}#{SharepointStorage::IDENTIFIER_SEPARATOR}#{item_id}"
|
||||
|
||||
def delete_created_folder(folder)
|
||||
Input::DeleteFolder.build(location: folder.id).bind do |input_data|
|
||||
Registry.resolve("share_point.commands.delete_folder").call(storage:, auth_strategy:, input_data:)
|
||||
Registry.resolve("sharepoint.commands.delete_folder").call(storage:, auth_strategy:, input_data:)
|
||||
end
|
||||
end
|
||||
end
|
||||
+9
-9
@@ -34,15 +34,15 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Commands
|
||||
RSpec.describe DeleteFolderCommand, :vcr, :webmock do
|
||||
let(:storage) { create(:share_point_storage, :sandbox) }
|
||||
let(:auth_strategy) { Registry["share_point.authentication.userless"].call }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox) }
|
||||
let(:auth_strategy) { Registry["sharepoint.authentication.userless"].call }
|
||||
let(:base_drive) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW" }
|
||||
|
||||
it "is registered as commands.share_point.delete_folder" do
|
||||
expect(Registry.resolve("share_point.commands.delete_folder")).to eq(described_class)
|
||||
it "is registered as commands.sharepoint.delete_folder" do
|
||||
expect(Registry.resolve("sharepoint.commands.delete_folder")).to eq(described_class)
|
||||
end
|
||||
|
||||
it ".call requires storage and input_data as keyword arguments" do
|
||||
@@ -52,11 +52,11 @@ module Storages
|
||||
expect(method.parameters).to contain_exactly(%i[keyreq storage], %i[keyreq auth_strategy], %i[keyreq input_data])
|
||||
end
|
||||
|
||||
it "deletes a folder", vcr: "share_point/delete_folder" do
|
||||
it "deletes a folder", vcr: "sharepoint/delete_folder" do
|
||||
create_result = Input::CreateFolder
|
||||
.build(folder_name: "To Be Deleted Soon", parent_location: composite_identifier(nil))
|
||||
.bind do |input_data|
|
||||
Registry.resolve("share_point.commands.create_folder").call(storage:, auth_strategy:, input_data:)
|
||||
Registry.resolve("sharepoint.commands.create_folder").call(storage:, auth_strategy:, input_data:)
|
||||
end
|
||||
|
||||
folder = create_result.value_or { fail("Folder Creation Failed") }
|
||||
@@ -66,7 +66,7 @@ module Storages
|
||||
end
|
||||
end
|
||||
|
||||
it "when the folder is not found, returns a failure", vcr: "share_point/delete_folder_not_found" do
|
||||
it "when the folder is not found, returns a failure", vcr: "sharepoint/delete_folder_not_found" do
|
||||
result = Input::DeleteFolder.build(location: composite_identifier("NOT_HERE")).bind do |input_data|
|
||||
described_class.call(storage:, auth_strategy:, input_data:)
|
||||
end
|
||||
@@ -77,7 +77,7 @@ module Storages
|
||||
|
||||
private
|
||||
|
||||
def composite_identifier(item_id) = "#{base_drive}#{SharePointStorage::IDENTIFIER_SEPARATOR}#{item_id}"
|
||||
def composite_identifier(item_id) = "#{base_drive}#{SharepointStorage::IDENTIFIER_SEPARATOR}#{item_id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
+8
-8
@@ -34,17 +34,17 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe DownloadLinkQuery, :vcr, :webmock do
|
||||
let(:user) { create(:user) }
|
||||
let(:storage) { create(:share_point_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:auth_strategy) { Registry["one_drive.authentication.user_bound"].call(user, storage) }
|
||||
|
||||
let(:drive_id) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY87vnZ6fgfvQanZHX-XCAyw" }
|
||||
let(:file_link) { create(:file_link, origin_id: "#{drive_id}||01ANJ53W4ELLSQL3JZHNA2MHKKHKAUQWNS") }
|
||||
let(:not_existent_file_link) { create(:file_link, origin_id: "#{drive_id}||IHaveTheHighGround") }
|
||||
let(:folder_file_link) { create(:file_link, origin_id: "#{drive_id}||01ANJ53W4MWZNYS4FOTNDI3UVTLEXUZ5TQ") }
|
||||
let(:file_link) { create(:file_link, origin_id: "#{drive_id}:01ANJ53W4ELLSQL3JZHNA2MHKKHKAUQWNS") }
|
||||
let(:not_existent_file_link) { create(:file_link, origin_id: "#{drive_id}:IHaveTheHighGround") }
|
||||
let(:folder_file_link) { create(:file_link, origin_id: "#{drive_id}:01ANJ53W4MWZNYS4FOTNDI3UVTLEXUZ5TQ") }
|
||||
|
||||
let(:input_data) { Input::DownloadLink.build(file_link:).value! }
|
||||
|
||||
@@ -59,7 +59,7 @@ module Storages
|
||||
end
|
||||
|
||||
context "with outbound request successful" do
|
||||
it "returns a result with a download url", vcr: "share_point/download_link_query_success" do
|
||||
it "returns a result with a download url", vcr: "sharepoint/download_link_query_success" do
|
||||
download_link = subject.call(auth_strategy:, input_data:)
|
||||
|
||||
expect(download_link).to be_success
|
||||
@@ -69,7 +69,7 @@ module Storages
|
||||
expect(uri.path).to eq("/sites/OPTest/_layouts/15/download.aspx")
|
||||
end
|
||||
|
||||
it "returns an error on folders", vcr: "share_point/download_link_query_folder" do
|
||||
it "returns an error on folders", vcr: "sharepoint/download_link_query_folder" do
|
||||
input_data = Input::DownloadLink.build(file_link: folder_file_link).value!
|
||||
|
||||
download_link = subject.call(auth_strategy:, input_data:)
|
||||
@@ -81,7 +81,7 @@ module Storages
|
||||
expect(error.code).to eq(:not_found)
|
||||
end
|
||||
|
||||
it "returns an error if the file is not found", vcr: "share_point/download_link_query_not_found" do
|
||||
it "returns an error if the file is not found", vcr: "sharepoint/download_link_query_not_found" do
|
||||
input_data = Input::DownloadLink.build(file_link: not_existent_file_link).value!
|
||||
|
||||
download_link = subject.call(auth_strategy:, input_data:)
|
||||
+11
-11
@@ -34,21 +34,21 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe FileInfoQuery, :webmock do
|
||||
let(:user) { create(:user) }
|
||||
let(:storage) { create(:share_point_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:drive_id) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY87vnZ6fgfvQanZHX-XCAyw" }
|
||||
|
||||
let(:auth_strategy) { Registry["share_point.authentication.user_bound"].call(user, storage) }
|
||||
let(:auth_strategy) { Registry["sharepoint.authentication.user_bound"].call(user, storage) }
|
||||
|
||||
let(:input_data) { Input::FileInfo.build(file_id:).value! }
|
||||
|
||||
it_behaves_like "adapter file_info_query: basic query setup"
|
||||
|
||||
context "with a file id requested", vcr: "share_point/file_info_query_success_file" do
|
||||
let(:file_id) { "#{drive_id}||01ANJ53W5UJK2CQO6IY5HLBVYBVNJ4TKHZ" }
|
||||
context "with a file id requested", vcr: "sharepoint/file_info_query_success_file" do
|
||||
let(:file_id) { "#{drive_id}:01ANJ53W5UJK2CQO6IY5HLBVYBVNJ4TKHZ" }
|
||||
let(:file_info) do
|
||||
Results::StorageFileInfo.new(
|
||||
id: "01ANJ53W5UJK2CQO6IY5HLBVYBVNJ4TKHZ",
|
||||
@@ -71,8 +71,8 @@ module Storages
|
||||
it_behaves_like "adapter file_info_query: successful file/folder response"
|
||||
end
|
||||
|
||||
context "with a folder id requested", vcr: "share_point/file_info_query_success_folder" do
|
||||
let(:file_id) { "#{drive_id}||01ANJ53WYP6TBC6T4G2RHIU4SVNEYGL6MF" }
|
||||
context "with a folder id requested", vcr: "sharepoint/file_info_query_success_folder" do
|
||||
let(:file_id) { "#{drive_id}:01ANJ53WYP6TBC6T4G2RHIU4SVNEYGL6MF" }
|
||||
let(:file_info) do
|
||||
Results::StorageFileInfo.new(
|
||||
id: "01ANJ53WYP6TBC6T4G2RHIU4SVNEYGL6MF",
|
||||
@@ -96,8 +96,8 @@ module Storages
|
||||
end
|
||||
|
||||
context "with a file with special characters in the path",
|
||||
vcr: "share_point/file_info_query_success_special_characters" do
|
||||
let(:file_id) { "#{drive_id}||01ANJ53W7BT4LBZ3PNORCYAXKILWJBLEBV" }
|
||||
vcr: "sharepoint/file_info_query_success_special_characters" do
|
||||
let(:file_id) { "#{drive_id}:01ANJ53W7BT4LBZ3PNORCYAXKILWJBLEBV" }
|
||||
let(:file_info) do
|
||||
Results::StorageFileInfo.new(
|
||||
id: "01ANJ53W7BT4LBZ3PNORCYAXKILWJBLEBV",
|
||||
@@ -120,8 +120,8 @@ module Storages
|
||||
it_behaves_like "adapter file_info_query: successful file/folder response"
|
||||
end
|
||||
|
||||
context "with a not existing file id", vcr: "share_point/file_info_query_not_found" do
|
||||
let(:file_id) { "#{drive_id}||not_existent" }
|
||||
context "with a not existing file id", vcr: "sharepoint/file_info_query_not_found" do
|
||||
let(:file_id) { "#{drive_id}:not_existent" }
|
||||
let(:error_source) { Internal::DriveItemQuery }
|
||||
|
||||
it_behaves_like "adapter file_info_query: not found"
|
||||
+9
-9
@@ -34,12 +34,12 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe FilesInfoQuery, :vcr, :webmock do
|
||||
let(:user) { create(:user) }
|
||||
let(:storage) { create(:share_point_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:auth_strategy) { Registry["share_point.authentication.user_bound"].call(user, storage) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:auth_strategy) { Registry["sharepoint.authentication.user_bound"].call(user, storage) }
|
||||
let(:input_data) { Input::FilesInfo.build(file_ids:).value! }
|
||||
|
||||
it_behaves_like "adapter files_info_query: basic query setup"
|
||||
@@ -51,13 +51,13 @@ module Storages
|
||||
it_behaves_like "adapter files_info_query: successful list response"
|
||||
end
|
||||
|
||||
context "with all outbound requests successful", vcr: "share_point/files_info_query_success" do
|
||||
context "with all outbound requests successful", vcr: "sharepoint/files_info_query_success" do
|
||||
let(:drive_id) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY87vnZ6fgfvQanZHX-XCAyw" }
|
||||
let(:file_ids) do
|
||||
%W[
|
||||
#{drive_id}||01ANJ53WYLXAJW5PXSCJB2CFCD42UPDKMI
|
||||
#{drive_id}||01ANJ53W4ELLSQL3JZHNA2MHKKHKAUQWNS
|
||||
#{drive_id}||01ANJ53W5UJK2CQO6IY5HLBVYBVNJ4TKHZ
|
||||
#{drive_id}:01ANJ53WYLXAJW5PXSCJB2CFCD42UPDKMI
|
||||
#{drive_id}:01ANJ53W4ELLSQL3JZHNA2MHKKHKAUQWNS
|
||||
#{drive_id}:01ANJ53W5UJK2CQO6IY5HLBVYBVNJ4TKHZ
|
||||
]
|
||||
end
|
||||
let(:expected_file_infos) do
|
||||
@@ -113,9 +113,9 @@ module Storages
|
||||
it_behaves_like "adapter files_info_query: successful list response"
|
||||
end
|
||||
|
||||
context "with one outbound request returning not found", vcr: "share_point/files_info_query_one_not_found" do
|
||||
context "with one outbound request returning not found", vcr: "sharepoint/files_info_query_one_not_found" do
|
||||
let(:drive_id) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY87vnZ6fgfvQanZHX-XCAyw" }
|
||||
let(:file_ids) { %W[#{drive_id}||01ANJ53W4ELLSQL3JZHNA2MHKKHKAUQWNS #{drive_id}||not_existent] }
|
||||
let(:file_ids) { %W[#{drive_id}:01ANJ53W4ELLSQL3JZHNA2MHKKHKAUQWNS #{drive_id}:not_existent] }
|
||||
let(:expected_file_infos) do
|
||||
[
|
||||
Results::StorageFileInfo.new(
|
||||
+22
-24
@@ -34,19 +34,18 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe FilesQuery, :webmock do
|
||||
let(:user) { create(:admin) }
|
||||
let(:storage) { create(:share_point_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, oauth_client_token_user: user) }
|
||||
|
||||
let(:auth_strategy) { Registry["share_point.authentication.userless"].call(false) }
|
||||
let(:auth_strategy) { Registry["sharepoint.authentication.userless"].call(false) }
|
||||
let(:input_data) { Input::Files.build(folder:).value! }
|
||||
|
||||
it_behaves_like "adapter files_query: basic query setup"
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
context "when parent folder is root", vcr: "share_point/files_query_root" do
|
||||
context "when parent folder is root", vcr: "sharepoint/files_query_root" do
|
||||
let(:folder) { "/" }
|
||||
let(:files_result) do
|
||||
Results::StorageFileCollection.new(
|
||||
@@ -119,13 +118,13 @@ module Storages
|
||||
it_behaves_like "adapter files_query: successful files response"
|
||||
end
|
||||
|
||||
context "when requesting a drive", vcr: "share_point/files_query_drive" do
|
||||
context "when requesting a drive", vcr: "sharepoint/files_query_drive" do
|
||||
let(:folder) { "/Marcello VCR" }
|
||||
let(:files_result) do
|
||||
Results::StorageFileCollection.new(
|
||||
files: [
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W5P3SUY3ZCDTRA3KLXRGA5A2M3S",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W5P3SUY3ZCDTRA3KLXRGA5A2M3S",
|
||||
name: "data",
|
||||
size: 12605,
|
||||
mime_type: "application/x-op-directory",
|
||||
@@ -137,7 +136,7 @@ module Storages
|
||||
permissions: %i[readable writeable]
|
||||
),
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W2MWJ6SKEZPHFGIAAB325KYYMPE",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W2MWJ6SKEZPHFGIAAB325KYYMPE",
|
||||
name: "empty",
|
||||
size: 0,
|
||||
mime_type: "application/x-op-directory",
|
||||
@@ -149,7 +148,7 @@ module Storages
|
||||
permissions: %i[readable writeable]
|
||||
),
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W7TITEF4WCHRBDKR7VMNUWZ33WD",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W7TITEF4WCHRBDKR7VMNUWZ33WD",
|
||||
name: "Folder with spaces",
|
||||
size: 0,
|
||||
mime_type: "application/x-op-directory",
|
||||
@@ -161,7 +160,7 @@ module Storages
|
||||
permissions: %i[readable writeable]
|
||||
),
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53WZVLAWJSVFKOFF3HLYZPMPUK6HI",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53WZVLAWJSVFKOFF3HLYZPMPUK6HI",
|
||||
name: "simply_oidc.jpg",
|
||||
size: 56483,
|
||||
mime_type: "image/jpeg",
|
||||
@@ -174,7 +173,7 @@ module Storages
|
||||
)
|
||||
],
|
||||
parent: Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:",
|
||||
name: "Marcello VCR",
|
||||
location: "/Marcello%20VCR",
|
||||
permissions: %i[readable writeable]
|
||||
@@ -188,14 +187,14 @@ module Storages
|
||||
it_behaves_like "adapter files_query: successful files response"
|
||||
end
|
||||
|
||||
context "when requesting an folder", vcr: "share_point/files_query_folder" do
|
||||
context "when requesting an folder", vcr: "sharepoint/files_query_folder" do
|
||||
let(:folder) { "/Marcello VCR/data" }
|
||||
|
||||
let(:files_result) do
|
||||
Results::StorageFileCollection.new(
|
||||
files: [
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W6DBDYX553L4REYNOMUI6XVMTO6",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W6DBDYX553L4REYNOMUI6XVMTO6",
|
||||
name: "subfolder",
|
||||
size: 11845,
|
||||
mime_type: "application/x-op-directory",
|
||||
@@ -207,7 +206,7 @@ module Storages
|
||||
permissions: %i[readable writeable]
|
||||
),
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W26P5RNXU7V2JBKCVQQAGGTO46A",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W26P5RNXU7V2JBKCVQQAGGTO46A",
|
||||
name: "edge one_drive_health_report_2025-07-22T16_03_25Z.txt",
|
||||
size: 760,
|
||||
mime_type: "text/plain",
|
||||
@@ -220,7 +219,7 @@ module Storages
|
||||
)
|
||||
],
|
||||
parent: Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W5P3SUY3ZCDTRA3KLXRGA5A2M3S",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W5P3SUY3ZCDTRA3KLXRGA5A2M3S",
|
||||
name: "data",
|
||||
location: "/Marcello%20VCR/data",
|
||||
permissions: %i[readable writeable]
|
||||
@@ -235,13 +234,13 @@ module Storages
|
||||
it_behaves_like "adapter files_query: successful files response"
|
||||
end
|
||||
|
||||
context "when requesting a sub folder", vcr: "share_point/files_query_sub_folder" do
|
||||
context "when requesting a sub folder", vcr: "sharepoint/files_query_sub_folder" do
|
||||
let(:folder) { "/Marcello VCR/data/subfolder" }
|
||||
let(:files_result) do
|
||||
Results::StorageFileCollection.new(
|
||||
files: [
|
||||
Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W7MUYDYQAA3WVEYDJQNZVSKNPGD",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W7MUYDYQAA3WVEYDJQNZVSKNPGD",
|
||||
name: "fw13-easy-effects.json",
|
||||
size: 11845,
|
||||
mime_type: "application/json",
|
||||
@@ -254,7 +253,7 @@ module Storages
|
||||
)
|
||||
],
|
||||
parent: Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W6DBDYX553L4REYNOMUI6XVMTO6",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W6DBDYX553L4REYNOMUI6XVMTO6",
|
||||
name: "subfolder",
|
||||
location: "/Marcello%20VCR/data/subfolder",
|
||||
permissions: %i[readable writeable]
|
||||
@@ -270,14 +269,14 @@ module Storages
|
||||
it_behaves_like "adapter files_query: successful files response"
|
||||
end
|
||||
|
||||
context "when requesting an empty folder", vcr: "share_point/files_query_empty_folder" do
|
||||
context "when requesting an empty folder", vcr: "sharepoint/files_query_empty_folder" do
|
||||
let(:folder) { "/Marcello VCR/empty" }
|
||||
|
||||
let(:files_result) do
|
||||
Results::StorageFileCollection.new(
|
||||
files: [],
|
||||
parent: Results::StorageFile.new(
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W2MWJ6SKEZPHFGIAAB325KYYMPE",
|
||||
id: "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W2MWJ6SKEZPHFGIAAB325KYYMPE",
|
||||
name: "empty",
|
||||
location: "/Marcello%20VCR/empty",
|
||||
permissions: %i[readable writeable]
|
||||
@@ -292,7 +291,7 @@ module Storages
|
||||
it_behaves_like "adapter files_query: successful files response"
|
||||
end
|
||||
|
||||
context "when requesting an empty library", vcr: "share_point/files_query_empty_drive" do
|
||||
context "when requesting an empty library", vcr: "sharepoint/files_query_empty_drive" do
|
||||
let(:folder) { "/Selected Permissions" }
|
||||
|
||||
let(:files_result) do
|
||||
@@ -313,18 +312,17 @@ module Storages
|
||||
it_behaves_like "adapter files_query: successful files response"
|
||||
end
|
||||
|
||||
context "when requesting an unknown file", vcr: "share_point/files_query_file_not_found" do
|
||||
context "when requesting an unknown file", vcr: "sharepoint/files_query_file_not_found" do
|
||||
let(:folder) { "/Marcello VCR/POTATO" }
|
||||
|
||||
it_behaves_like "adapter files_query: not found", Internal::ChildrenQuery
|
||||
end
|
||||
|
||||
context "when requestion an unknown drive", vcr: "share_point/files_query_drive_not_found" do
|
||||
context "when requestion an unknown drive", vcr: "sharepoint/files_query_drive_not_found" do
|
||||
let(:folder) { "/That is no moon" }
|
||||
|
||||
it_behaves_like "adapter files_query: not found"
|
||||
end
|
||||
# rubocop:enable Layout/LineLength
|
||||
end
|
||||
end
|
||||
end
|
||||
+8
-8
@@ -34,19 +34,19 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe OpenFileLinkQuery, :vcr, :webmock do
|
||||
let(:user) { create(:user) }
|
||||
let(:storage) { create(:share_point_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:auth_strategy) { Registry.resolve("share_point.authentication.user_bound").call(user, storage) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:auth_strategy) { Registry.resolve("sharepoint.authentication.user_bound").call(user, storage) }
|
||||
let(:drive_id) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY87vnZ6fgfvQanZHX-XCAyw" }
|
||||
let(:separator) { SharePointStorage::IDENTIFIER_SEPARATOR }
|
||||
let(:separator) { SharepointStorage::IDENTIFIER_SEPARATOR }
|
||||
|
||||
it_behaves_like "adapter open_file_link_query: basic query setup"
|
||||
|
||||
context "with outbound requests successful" do
|
||||
context "with open location flag not set", vcr: "share_point/open_file_link_query_success" do
|
||||
context "with open location flag not set", vcr: "sharepoint/open_file_link_query_success" do
|
||||
let(:file_id) { "#{drive_id}#{separator}01ANJ53WYLXAJW5PXSCJB2CFCD42UPDKMI" }
|
||||
let(:input_data) { Input::OpenFileLink.build(file_id:).value! }
|
||||
let(:open_file_link) { "https://ymt6d.sharepoint.com/sites/OPTest/Shared%20Documents/Folder" }
|
||||
@@ -54,7 +54,7 @@ module Storages
|
||||
it_behaves_like "adapter open_file_link_query: successful link response"
|
||||
end
|
||||
|
||||
context "with open location flag set", vcr: "share_point/open_file_link_location_query_success" do
|
||||
context "with open location flag set", vcr: "sharepoint/open_file_link_location_query_success" do
|
||||
let(:file_id) { "#{drive_id}#{separator}01ANJ53WYLXAJW5PXSCJB2CFCD42UPDKMI" }
|
||||
let(:input_data) { Input::OpenFileLink.build(file_id:, open_location: true).value! }
|
||||
let(:open_file_link) { "https://ymt6d.sharepoint.com/sites/OPTest/Shared%20Documents" }
|
||||
@@ -62,7 +62,7 @@ module Storages
|
||||
it_behaves_like "adapter open_file_link_query: successful link response"
|
||||
|
||||
context "if file id already points at root element",
|
||||
vcr: "share_point/open_file_link_location_on_root_query_success" do
|
||||
vcr: "sharepoint/open_file_link_location_on_root_query_success" do
|
||||
let(:file_id) { "#{drive_id}#{separator}01ANJ53W56Y2GOVW7725BZO354PWSELRRZ" }
|
||||
|
||||
it_behaves_like "adapter open_file_link_query: successful link response"
|
||||
@@ -70,7 +70,7 @@ module Storages
|
||||
end
|
||||
end
|
||||
|
||||
context "with not existent file id", vcr: "share_point/open_file_link_query_not_found" do
|
||||
context "with not existent file id", vcr: "sharepoint/open_file_link_query_not_found" do
|
||||
let(:file_id) { "#{drive_id}#{separator}YouShallNotPass" }
|
||||
let(:input_data) { Input::OpenFileLink.build(file_id:).value! }
|
||||
let(:error_source) { Internal::DriveItemQuery }
|
||||
+2
-2
@@ -34,10 +34,10 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe OpenStorageQuery do
|
||||
let(:storage) { create(:share_point_storage, :sandbox) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox) }
|
||||
|
||||
it "responds to .call" do
|
||||
expect(described_class).to respond_to(:call)
|
||||
+8
-8
@@ -34,18 +34,18 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Queries
|
||||
RSpec.describe UploadLinkQuery, :webmock do
|
||||
let(:storage) { create(:share_point_storage, :sandbox) }
|
||||
let(:auth_strategy) { Registry["share_point.authentication.userless"].call }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox) }
|
||||
let(:auth_strategy) { Registry["sharepoint.authentication.userless"].call }
|
||||
let(:upload_method) { :put }
|
||||
let(:input_data) { Input::UploadLink.build(folder_id:, file_name:).value! }
|
||||
let(:file_name) { "DeathStart_blueprints.tiff" }
|
||||
|
||||
it_behaves_like "adapter upload_link_query: basic query setup"
|
||||
|
||||
context "when creating an upload link to the root folder of a list", vcr: "share_point/upload_link_success" do
|
||||
context "when creating an upload link to the root folder of a list", vcr: "sharepoint/upload_link_success" do
|
||||
let(:folder_id) { "b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY8Qconfm2i6SKEoCmuGYqQK" }
|
||||
|
||||
let(:token) do
|
||||
@@ -69,9 +69,9 @@ module Storages
|
||||
it_behaves_like "adapter upload_link_query: successful upload link response"
|
||||
end
|
||||
|
||||
context "when creating an upload link to a subfolder on a list", vcr: "share_point/upload_link_subfolder" do
|
||||
context "when creating an upload link to a subfolder on a list", vcr: "sharepoint/upload_link_subfolder" do
|
||||
let(:folder_id) do
|
||||
"b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW||01ANJ53W5P3SUY3ZCDTRA3KLXRGA5A2M3S"
|
||||
"b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY9jo6leJDqrT7muzvmiWjFW:01ANJ53W5P3SUY3ZCDTRA3KLXRGA5A2M3S"
|
||||
end
|
||||
let(:token) do
|
||||
"v1.eyJzaXRlaWQiOiIxMDk5ZTMxNS1kMGM3LTQ3YzctODY0MC1hYTk1MDRiNzBmZmYiLCJhcHBfZGlzcGxheW5hbWUiOiJPUCBTZWx" \
|
||||
@@ -93,11 +93,11 @@ module Storages
|
||||
it_behaves_like "adapter upload_link_query: successful upload link response"
|
||||
end
|
||||
|
||||
context "when requesting an upload link for a not existing file", vcr: "share_point/upload_link_not_found" do
|
||||
context "when requesting an upload link for a not existing file", vcr: "sharepoint/upload_link_not_found" do
|
||||
let(:input_data) do
|
||||
Input::UploadLink.build(
|
||||
folder_id:
|
||||
"b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY8Qconfm2i6SKEoCmuGYqQK||04AZJL5PN6Y2GOVW7725BZO354PWSELRRZ",
|
||||
"b!FeOZEMfQx0eGQKqVBLcP__BG8mq-4-9FuRqOyk3MXY8Qconfm2i6SKEoCmuGYqQK:04AZJL5PN6Y2GOVW7725BZO354PWSELRRZ",
|
||||
file_name: "DeathStart_blueprints.tiff"
|
||||
).value!
|
||||
end
|
||||
+3
-3
@@ -34,10 +34,10 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
RSpec.describe SharePointContract, :storage_server_helpers, :webmock do
|
||||
module Sharepoint
|
||||
RSpec.describe SharepointContract, :storage_server_helpers, :webmock do
|
||||
let(:current_user) { create(:admin) }
|
||||
let(:storage) { build(:share_point_storage, :with_tenant_id) }
|
||||
let(:storage) { build(:sharepoint_storage, :with_tenant_id) }
|
||||
|
||||
# As the SharePointContract is selected by the BaseContract to make writable attributes available,
|
||||
# the BaseContract needs to be instantiated here.
|
||||
+2
-2
@@ -30,10 +30,10 @@
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Storages::Adapters::Providers::SharePoint::StorageWizard do
|
||||
RSpec.describe Storages::Adapters::Providers::Sharepoint::StorageWizard do
|
||||
subject(:wizard) { described_class.new(model:, user:) }
|
||||
|
||||
let(:model) { Storages::SharePointStorage.new }
|
||||
let(:model) { Storages::SharepointStorage.new }
|
||||
let(:user) { create(:admin) }
|
||||
|
||||
before do
|
||||
+4
-4
@@ -3,12 +3,12 @@
|
||||
require "spec_helper"
|
||||
require_module_spec_helper
|
||||
|
||||
RSpec.describe Storages::Adapters::Providers::SharePoint::Validators::AuthenticationValidator, :webmock do
|
||||
RSpec.describe Storages::Adapters::Providers::Sharepoint::Validators::AuthenticationValidator, :webmock do
|
||||
subject(:validator) { described_class.new(storage) }
|
||||
|
||||
context "when using OAuth2" do
|
||||
let(:user) { create(:user) }
|
||||
let(:storage) { create(:share_point_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, oauth_client_token_user: user) }
|
||||
let(:error) { Storages::Adapters::Results::Error.new(code: :unauthorized, source: self) }
|
||||
|
||||
before { User.current = user }
|
||||
@@ -17,7 +17,7 @@ RSpec.describe Storages::Adapters::Providers::SharePoint::Validators::Authentica
|
||||
expect(described_class.key).to eq(:authentication)
|
||||
end
|
||||
|
||||
it "passes when the user has a token and the request works", vcr: "share_point/user_query_success" do
|
||||
it "passes when the user has a token and the request works", vcr: "sharepoint/user_query_success" do
|
||||
expect(validator.call).to be_success
|
||||
end
|
||||
|
||||
@@ -31,7 +31,7 @@ RSpec.describe Storages::Adapters::Providers::SharePoint::Validators::Authentica
|
||||
end
|
||||
|
||||
it "returns a failure if the remote call failed" do
|
||||
Storages::Adapters::Registry.stub("share_point.queries.user", ->(_) { Failure(error) })
|
||||
Storages::Adapters::Registry.stub("sharepoint.queries.user", ->(_) { Failure(error) })
|
||||
|
||||
result = validator.call
|
||||
expect(result[:user_bound_request]).to be_a_failure
|
||||
+9
-9
@@ -6,15 +6,15 @@ require_module_spec_helper
|
||||
module Storages
|
||||
module Adapters
|
||||
module Providers
|
||||
module SharePoint
|
||||
module Sharepoint
|
||||
module Validators
|
||||
RSpec.describe StorageConfigurationValidator, :webmock do
|
||||
let(:storage) { create(:share_point_storage, :sandbox, :as_automatically_managed) }
|
||||
let(:storage) { create(:sharepoint_storage, :sandbox, :as_automatically_managed) }
|
||||
let(:error) { Results::Error.new(code: error_code, source: self) }
|
||||
|
||||
subject(:validator) { described_class.new(storage) }
|
||||
|
||||
describe "success", vcr: "share_point/files_query_userless" do
|
||||
describe "success", vcr: "sharepoint/files_query_userless" do
|
||||
it "returns a GroupValidationResult" do
|
||||
results = validator.call
|
||||
|
||||
@@ -25,7 +25,7 @@ module Storages
|
||||
|
||||
describe "failure" do
|
||||
let(:files_double) { class_double(Queries::FilesQuery) }
|
||||
let(:auth_strategy) { Registry["share_point.authentication.userless"].call }
|
||||
let(:auth_strategy) { Registry["sharepoint.authentication.userless"].call }
|
||||
let(:input_data) { Input::Files.build(folder: "/").value! }
|
||||
let(:result) { Success() }
|
||||
|
||||
@@ -34,7 +34,7 @@ module Storages
|
||||
end
|
||||
|
||||
context "when the storage isn't configured" do
|
||||
let(:storage) { create(:share_point_storage) }
|
||||
let(:storage) { create(:sharepoint_storage) }
|
||||
|
||||
it "the check fails" do
|
||||
results = validator.call
|
||||
@@ -44,7 +44,7 @@ module Storages
|
||||
end
|
||||
|
||||
context "when the tenant id is wrong" do
|
||||
it "but looks like an actual valid value", vcr: "share_point/validation_wrong_tenant_id" do
|
||||
it "but looks like an actual valid value", vcr: "sharepoint/validation_wrong_tenant_id" do
|
||||
storage.tenant_id = "itdoesnotexists9000.sharepoint.com"
|
||||
results = described_class.new(storage).call
|
||||
|
||||
@@ -52,7 +52,7 @@ module Storages
|
||||
expect(results[:tenant_id].code).to eq(:sp_tenant_id_invalid)
|
||||
end
|
||||
|
||||
it "but is blatantly wrong", vcr: "share_point/validation_absurd_tenant_id" do
|
||||
it "but is blatantly wrong", vcr: "sharepoint/validation_absurd_tenant_id" do
|
||||
storage.tenant_id = "wrong"
|
||||
results = described_class.new(storage).call
|
||||
|
||||
@@ -62,7 +62,7 @@ module Storages
|
||||
end
|
||||
|
||||
context "when the client secret is wrong" do
|
||||
it "fails the check", vcr: "share_point/validation_wrong_client_secret" do
|
||||
it "fails the check", vcr: "sharepoint/validation_wrong_client_secret" do
|
||||
storage.oauth_client.client_secret = "wrong"
|
||||
results = described_class.new(storage).call
|
||||
|
||||
@@ -72,7 +72,7 @@ module Storages
|
||||
end
|
||||
|
||||
context "when the client id is wrong" do
|
||||
it "fails the check", vcr: "share_point/validation_wrong_client_id" do
|
||||
it "fails the check", vcr: "sharepoint/validation_wrong_client_id" do
|
||||
storage.oauth_client.client_id = "wrong"
|
||||
results = described_class.new(storage).call
|
||||
|
||||
@@ -70,13 +70,13 @@ RSpec.shared_examples_for "file_link contract" do
|
||||
context "when empty" do
|
||||
let(:file_link_attributes) { { origin_id: "" } }
|
||||
|
||||
include_examples "contract is invalid", origin_id: %i[blank too_short]
|
||||
include_examples "contract is invalid", origin_id: %i[blank]
|
||||
end
|
||||
|
||||
context "when nil" do
|
||||
let(:file_link_attributes) { { origin_id: nil } }
|
||||
|
||||
include_examples "contract is invalid", origin_id: %i[blank too_short]
|
||||
include_examples "contract is invalid", origin_id: %i[blank]
|
||||
end
|
||||
|
||||
context "when numeric" do
|
||||
@@ -96,12 +96,6 @@ RSpec.shared_examples_for "file_link contract" do
|
||||
|
||||
include_examples "contract is valid"
|
||||
end
|
||||
|
||||
context "when longer than 100 characters" do
|
||||
let(:file_link_attributes) { { origin_id: "1" * 201 } }
|
||||
|
||||
include_examples "contract is invalid", origin_id: :too_long
|
||||
end
|
||||
end
|
||||
|
||||
describe "origin_name" do
|
||||
|
||||
@@ -232,9 +232,9 @@ FactoryBot.define do
|
||||
end
|
||||
end
|
||||
|
||||
factory :share_point_storage,
|
||||
factory :sharepoint_storage,
|
||||
parent: :storage,
|
||||
class: "::Storages::SharePointStorage" do
|
||||
class: "::Storages::SharepointStorage" do
|
||||
host { "https://openproject.sharepoint.com/sites/ProjectX" }
|
||||
automatically_managed { false }
|
||||
|
||||
@@ -247,8 +247,8 @@ FactoryBot.define do
|
||||
end
|
||||
|
||||
trait :sandbox do
|
||||
tenant_id { ENV.fetch("SHARE_POINT_TEST_TENANT_ID", "e36f1dbc-fdae-427e-b61b-0d96ddfb81a4") }
|
||||
host { ENV.fetch("SHARE_POINT_TEST_HOST", "https://ymt6d.sharepoint.com/sites/OPTest") }
|
||||
tenant_id { ENV.fetch("SHAREPOINT_TEST_TENANT_ID", "e36f1dbc-fdae-427e-b61b-0d96ddfb81a4") }
|
||||
host { ENV.fetch("SHAREPOINT_TEST_HOST", "https://ymt6d.sharepoint.com/sites/OPTest") }
|
||||
|
||||
transient do
|
||||
oauth_client_token_user { association :user }
|
||||
@@ -256,18 +256,18 @@ FactoryBot.define do
|
||||
|
||||
after(:create) do |storage, evaluator|
|
||||
create(:oauth_client,
|
||||
client_id: ENV.fetch("SHARE_POINT_TEST_OAUTH_CLIENT_ID",
|
||||
client_id: ENV.fetch("SHAREPOINT_TEST_OAUTH_CLIENT_ID",
|
||||
"MISSING_SHARE_POINT_TEST_OAUTH_CLIENT_ID"),
|
||||
client_secret: ENV.fetch("SHARE_POINT_TEST_OAUTH_CLIENT_SECRET",
|
||||
client_secret: ENV.fetch("SHAREPOINT_TEST_OAUTH_CLIENT_SECRET",
|
||||
"MISSING_SHARE_POINT_TEST_OAUTH_CLIENT_SECRET"),
|
||||
integration: storage)
|
||||
|
||||
create(:oauth_client_token,
|
||||
oauth_client: storage.oauth_client,
|
||||
user: evaluator.oauth_client_token_user,
|
||||
access_token: ENV.fetch("SHARE_POINT_TEST_OAUTH_CLIENT_ACCESS_TOKEN",
|
||||
access_token: ENV.fetch("SHAREPOINT_TEST_OAUTH_CLIENT_ACCESS_TOKEN",
|
||||
"MISSING_SHARE_POINT_TEST_OAUTH_CLIENT_ACCESS_TOKEN"),
|
||||
refresh_token: ENV.fetch("SHARE_POINT_TEST_OAUTH_CLIENT_REFRESH_TOKEN",
|
||||
refresh_token: ENV.fetch("SHAREPOINT_TEST_OAUTH_CLIENT_REFRESH_TOKEN",
|
||||
"MISSING_SHARE_POINT_TEST_OAUTH_CLIENT_REFRESH_TOKEN"),
|
||||
token_type: "bearer")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user