diff --git a/packages/api/src/@core/utils/types/original/original.file-storage.ts b/packages/api/src/@core/utils/types/original/original.file-storage.ts index 25c49901b..415a259e7 100644 --- a/packages/api/src/@core/utils/types/original/original.file-storage.ts +++ b/packages/api/src/@core/utils/types/original/original.file-storage.ts @@ -1,3 +1,6 @@ +import { BoxSharedlinkInput, BoxSharedlinkOutput } from '@filestorage/sharedlink/services/box/types'; +import { OnedriveSharedlinkInput, OnedriveSharedlinkOutput } from '@filestorage/sharedlink/services/onedrive/types'; + import { OnedrivePermissionInput, OnedrivePermissionOutput } from '@filestorage/permission/services/onedrive/types'; import { OnedriveGroupInput, OnedriveGroupOutput } from '@filestorage/group/services/onedrive/types'; @@ -90,3 +93,7 @@ export type FileStorageObjectOutput = | OriginalDriveOutput | OriginalGroupOutput | OriginalUserOutput; + +export type OriginalSharedlinkInput = BoxSharedlinkInput | OnedriveSharedlinkInput; + +export type OriginalSharedlinkOutput = BoxSharedlinkOutput | OnedriveSharedlinkOutput; diff --git a/packages/api/src/filestorage/sharedlink/services/onedrive/index.ts b/packages/api/src/filestorage/sharedlink/services/onedrive/index.ts new file mode 100644 index 000000000..bde2fc587 --- /dev/null +++ b/packages/api/src/filestorage/sharedlink/services/onedrive/index.ts @@ -0,0 +1,81 @@ +import { Injectable } from '@nestjs/common'; +import { ISharedLinkService } from '@filestorage/sharedlink/types'; +import { FileStorageObject } from '@filestorage/@lib/@types'; +import axios from 'axios'; +import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; +import { LoggerService } from '@@core/@core-services/logger/logger.service'; +import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors'; +import { EncryptionService } from '@@core/@core-services/encryption/encryption.service'; +import { ApiResponse } from '@@core/utils/types'; +import { ServiceRegistry } from '../registry.service'; +import { SyncParam } from '@@core/utils/types/interface'; +import { OnedriveSharedLinkInput, OnedriveSharedLinkOutput } from './types'; + +@Injectable() +export class OnedriveService implements ISharedLinkService { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + private registry: ServiceRegistry, + ) { + this.logger.setContext( + FileStorageObject.sharedlink.toUpperCase() + ':' + OnedriveService.name, + ); + this.registry.registerService('onedrive', this); + } + + async sync( + data: SyncParam, + ): Promise> { + try { + const { linkedUserId, extra } = data; + // TODO: where it comes from ?? extra?: { object_name: 'folder' | 'file'; value: string }, + + const connection = await this.prisma.connections.findFirst({ + where: { + id_linked_user: linkedUserId, + provider_slug: 'onedrive', + vertical: 'filestorage', + }, + }); + let remote_id; + if (extra.object_name == 'folder') { + const a = await this.prisma.fs_folders.findUnique({ + where: { + id_fs_folder: extra.value, + }, + }); + remote_id = a.remote_id; + } + if (extra.object_name == 'file') { + const a = await this.prisma.fs_files.findUnique({ + where: { + id_fs_file: extra.value, + }, + }); + remote_id = a.remote_id; + } + + const resp = await axios.get( + `${connection.account_url}/v1.0/drive/items/${remote_id}/permissions`, + // Same url as onedrive permissions + // We might use POST /drives/{driveId}/items/{itemId}/createLink later + { + headers: { + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, + }, + }, + ); + return { + data: resp.data, + message: 'Onedrive sharedlinks retrieved', + statusCode: resp.status, // 200 || 201 + }; + } catch (error) { + throw error; + } + } +} diff --git a/packages/api/src/filestorage/sharedlink/services/onedrive/mappers.ts b/packages/api/src/filestorage/sharedlink/services/onedrive/mappers.ts new file mode 100644 index 000000000..dbd3a3852 --- /dev/null +++ b/packages/api/src/filestorage/sharedlink/services/onedrive/mappers.ts @@ -0,0 +1,96 @@ +import { + UnifiedFilestorageSharedlinkInput, + UnifiedFilestorageSharedlinkOutput, +} from '@filestorage/sharedlink/types/model.unified'; +import { ISharedLinkMapper } from '@filestorage/sharedlink/types'; +import { Utils } from '@filestorage/@lib/@utils'; +import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry'; +import { Injectable } from '@nestjs/common'; +import { OriginalPermissionOutput } from '@@core/utils/types/original/original.file-storage'; +import { UnifiedFilestoragePermissionOutput } from '@filestorage/permission/types/model.unified'; +import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service'; +import { OnedriveSharedLinkInput, OnedriveSharedLinkOutput } from './types'; + +@Injectable() +export class OnedriveSharedLinkMapper implements ISharedLinkMapper { + constructor( + private mappersRegistry: MappersRegistry, + private utils: Utils, + private ingestService: IngestDataService, + ) { + this.mappersRegistry.registerService( + 'filestorage', + 'sharedlink', + 'onedrive', + this, + ); + } + + async desunify( + source: UnifiedFilestorageSharedlinkInput, + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): Promise { + return; + } + + async unify( + source: OnedriveSharedLinkOutput | OnedriveSharedLinkOutput[], + connectionId: string, + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): Promise< + UnifiedFilestorageSharedlinkOutput | UnifiedFilestorageSharedlinkOutput[] + > { + if (!Array.isArray(source)) { + return await this.mapSingleSharedLinkToUnified( + source, + connectionId, + customFieldMappings, + ); + } + // Handling array of OnedriveSharedLinkOutput + return Promise.all( + source.map((sharedlink) => + this.mapSingleSharedLinkToUnified( + sharedlink, + connectionId, + customFieldMappings, + ), + ), + ); + } + + private async mapSingleSharedLinkToUnified( + sharedlink: OnedriveSharedLinkOutput, + connectionId: string, + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): Promise { + const field_mappings: { [key: string]: any } = {}; + if (customFieldMappings) { + customFieldMappings.forEach((mapping) => { + field_mappings[mapping.slug] = sharedlink[mapping.remote_id]; + }); + } + + return { + remote_id: sharedlink.id, + remote_data: sharedlink, + url: sharedlink.link?.webUrl, + download_url: null, + folder_id: null, + file_id: null, + scope: sharedlink.link?.scope, + password_protected: sharedlink.hasPassword, + password: null, + field_mappings, + }; + } +} diff --git a/packages/api/src/filestorage/sharedlink/sharedlink.module.ts b/packages/api/src/filestorage/sharedlink/sharedlink.module.ts index 86dbb8b78..296da41ad 100644 --- a/packages/api/src/filestorage/sharedlink/sharedlink.module.ts +++ b/packages/api/src/filestorage/sharedlink/sharedlink.module.ts @@ -1,3 +1,7 @@ +import { OnedriveSharedlinkMapper } from './services/onedrive/mappers'; +import { BoxSharedlinkMapper } from './services/box/mappers'; +import { OnedriveService } from './services/onedrive'; +import { BoxService } from './services/box'; import { EncryptionService } from '@@core/@core-services/encryption/encryption.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service'; @@ -31,6 +35,10 @@ import { Utils } from '@filestorage/@lib/@utils'; Utils, /* PROVIDERS SERVICES */ BoxSharedLinkMapper, + BoxService, + OnedriveService, + BoxSharedlinkMapper, + OnedriveSharedlinkMapper, ], exports: [SyncService], })