diff --git a/src/@types/commands.ts b/src/@types/commands.ts index cf2069824..2ab14c7ec 100644 --- a/src/@types/commands.ts +++ b/src/@types/commands.ts @@ -7,15 +7,7 @@ import type { ComputeResourceRequest, DBComputeJobMetadata } from './C2D/C2D.js' -import { - ArweaveFileObject, - FileObjectType, - EncryptMethod, - FtpFileObject, - IpfsFileObject, - UrlFileObject, - BaseFileObject -} from './fileObject' +import { FileObjectType, StorageObject, EncryptMethod } from './fileObject' export interface Command { command: string // command name @@ -69,7 +61,7 @@ export interface FileInfoCommand extends Command { did?: string serviceId?: string fileIndex?: number - file?: UrlFileObject | ArweaveFileObject | IpfsFileObject | FtpFileObject + file?: StorageObject checksum?: boolean } // group these 2 @@ -135,7 +127,7 @@ export interface EncryptFileCommand extends Command { consumerAddress: string signature: string encryptionType?: EncryptMethod.AES | EncryptMethod.ECIES - files?: BaseFileObject + files?: StorageObject rawData?: Buffer policyServer?: any // object to pass to policy server } diff --git a/src/@types/fileObject.ts b/src/@types/fileObject.ts index c9526fd74..23803bc1f 100644 --- a/src/@types/fileObject.ts +++ b/src/@types/fileObject.ts @@ -87,11 +87,10 @@ export interface FileInfoResponse { encryptMethod?: EncryptMethod } -export interface FileInfoHttpRequest { - type?: FileObjectType - did?: string - hash?: string - url?: string - transactionId?: string - serviceId?: string -} +export type FileInfoHttpRequest = + | StorageObject + | { + did?: string + serviceId?: string + checksum?: boolean + } diff --git a/src/components/core/handler/fileInfoHandler.ts b/src/components/core/handler/fileInfoHandler.ts index c9579fea5..d11df081b 100644 --- a/src/components/core/handler/fileInfoHandler.ts +++ b/src/components/core/handler/fileInfoHandler.ts @@ -1,6 +1,6 @@ import { Readable } from 'stream' import { P2PCommandResponse } from '../../../@types/index.js' -import { StorageObject } from '../../../@types/fileObject.js' +import { FileObjectType, StorageObject } from '../../../@types/fileObject.js' import { OceanNodeConfig } from '../../../@types/OceanNode.js' import { FileInfoCommand } from '../../../@types/commands.js' import { CORE_LOGGER } from '../../../utils/logging/common.js' @@ -54,6 +54,17 @@ export class FileInfoHandler extends CommandHandler { return buildInvalidRequestMessage('Invalid Request: no fields are present!') } } + + const matchesRegex = (value: string, regex: RegExp): boolean => regex.test(value) + if (command.did && !matchesRegex(command.did, /^did:op/)) { + return buildInvalidRequestMessage('Invalid Request: invalid did!') + } + if (command.type && !Object.values(FileObjectType).includes(command.type)) { + return buildInvalidRequestMessage( + 'Invalid Request: type must be one of ' + Object.values(FileObjectType).join(', ') + ) + } + return validation } diff --git a/src/components/httpRoutes/fileInfo.ts b/src/components/httpRoutes/fileInfo.ts index ee6df98d7..85925b352 100644 --- a/src/components/httpRoutes/fileInfo.ts +++ b/src/components/httpRoutes/fileInfo.ts @@ -1,11 +1,8 @@ import express, { Request, Response } from 'express' import { - ArweaveFileObject, FileInfoHttpRequest, FileObjectType, - FtpFileObject, - IpfsFileObject, - UrlFileObject + StorageObject } from '../../@types/fileObject.js' import { PROTOCOL_COMMANDS, SERVICES_API_BASE_PATH } from '../../utils/constants.js' import { FileInfoHandler } from '../core/handler/fileInfoHandler.js' @@ -16,24 +13,6 @@ export const fileInfoRoute = express.Router() fileInfoRoute.use(express.json()) // Ensure JSON parsing middleware is used // Validation function -const validateFileInfoRequest = (req: FileInfoHttpRequest): boolean => { - // Helper function to check if a string matches a regular expression - const matchesRegex = (value: string, regex: RegExp): boolean => regex.test(value) - - if (!req.type && !req.did) return false // either 'type' or 'did' is required - if (req.type && !['ipfs', 'url', 'arweave', 's3', 'ftp'].includes(req.type)) { - return false // 'type' must be one of the allowed values - } - if (req.did && !matchesRegex(req.did, /^did:op/)) return false // 'did' must match the regex - if (req.type === 'ipfs' && !req.hash) return false // 'hash' is required if 'type' is 'ipfs' - if (req.type === 'url' && !req.url) return false // 'url' is required if 'type' is 'url' - if (req.type === 'ftp' && !req.url) return false // 'url' is required if 'type' is 'ftp' - if (req.type === 'arweave' && !req.transactionId) return false // 'transactionId' is required if 'type' is 'arweave' - if (!req.type && !req.serviceId) return false // 'serviceId' is required if 'type' is not provided - - return true -} - fileInfoRoute.post( `${SERVICES_API_BASE_PATH}/fileInfo`, express.urlencoded({ extended: true, type: '*/*' }), @@ -41,71 +20,41 @@ fileInfoRoute.post( const fileInfoReq: FileInfoHttpRequest = req.body as unknown as FileInfoHttpRequest HTTP_LOGGER.logMessage(`FileInfo request received: ${JSON.stringify(req.body)}`, true) - if (!validateFileInfoRequest(fileInfoReq)) { - res.status(400).send('Invalid request parameters') - return - } - try { + const hasType = + 'type' in fileInfoReq && + fileInfoReq.type != null && + String(fileInfoReq.type).trim() !== '' + const hasDid = + 'did' in fileInfoReq && + fileInfoReq.did != null && + String(fileInfoReq.did).trim() !== '' + if (!hasType && !hasDid) { + res.status(400).send('Invalid request parameters') + return + } // Retrieve the file info - let fileObject: UrlFileObject | IpfsFileObject | ArweaveFileObject | FtpFileObject + let fileObject: StorageObject let fileInfoTask: FileInfoCommand - if (fileInfoReq.did && fileInfoReq.serviceId) { + if (`did` in fileInfoReq && fileInfoReq.did && fileInfoReq.serviceId) { fileInfoTask = { command: PROTOCOL_COMMANDS.FILE_INFO, did: fileInfoReq.did, serviceId: fileInfoReq.serviceId, caller: req.caller } - } else if (fileInfoReq.type === 'url' && fileInfoReq.url) { - fileObject = { - type: 'url', - url: fileInfoReq.url, - method: 'GET' - } as UrlFileObject - fileInfoTask = { - command: PROTOCOL_COMMANDS.FILE_INFO, - file: fileObject, - type: fileObject.type as FileObjectType, - caller: req.caller - } - } else if (fileInfoReq.type === 'ipfs' && fileInfoReq.hash) { - fileObject = { - type: 'ipfs', - hash: fileInfoReq.hash, - method: 'GET' - } as IpfsFileObject - fileInfoTask = { - command: PROTOCOL_COMMANDS.FILE_INFO, - file: fileObject, - type: fileObject.type as FileObjectType, - caller: req.caller - } - } else if (fileInfoReq.type === 'arweave' && fileInfoReq.transactionId) { - fileObject = { - type: 'arweave', - transactionId: fileInfoReq.transactionId, - method: 'GET' - } as ArweaveFileObject + } else { + fileObject = { ...fileInfoReq } as StorageObject + fileInfoTask = { command: PROTOCOL_COMMANDS.FILE_INFO, file: fileObject, type: fileObject.type as FileObjectType, caller: req.caller } - } else if (fileInfoReq.type === 'ftp' && fileInfoReq.url) { - fileObject = { - type: 'ftp', - url: fileInfoReq.url - } as FtpFileObject - fileInfoTask = { - command: PROTOCOL_COMMANDS.FILE_INFO, - file: fileObject, - type: FileObjectType.FTP, - caller: req.caller - } } + const response = await new FileInfoHandler(req.oceanNode).handle(fileInfoTask) if (response.stream) { res.status(response.status.httpStatus) diff --git a/src/components/httpRoutes/provider.ts b/src/components/httpRoutes/provider.ts index f44a05744..faef472d1 100644 --- a/src/components/httpRoutes/provider.ts +++ b/src/components/httpRoutes/provider.ts @@ -10,7 +10,7 @@ import { DecryptDdoHandler } from '../core/handler/ddoHandler.js' import { DownloadHandler } from '../core/handler/downloadHandler.js' import { DownloadCommand } from '../../@types/commands.js' import { FeesHandler } from '../core/handler/feesHandler.js' -import { BaseFileObject, EncryptMethod } from '../../@types/fileObject.js' +import { StorageObject, EncryptMethod } from '../../@types/fileObject.js' import { P2PCommandResponse } from '../../@types/OceanNode.js' import { getEncryptMethodFromString } from '../../utils/crypt.js' @@ -119,7 +119,7 @@ providerRoutes.post(`${SERVICES_API_BASE_PATH}/encryptFile`, async (req, res) => if (req.is('application/json')) { // body as fileObject result = await new EncryptFileHandler(req.oceanNode).handle({ - files: req.body as BaseFileObject, + files: req.body as StorageObject, encryptionType: encryptMethod, command: PROTOCOL_COMMANDS.ENCRYPT_FILE, caller: req.caller,