diff --git a/apps/meteor/server/sdk/index.ts b/apps/meteor/server/sdk/index.ts index 42724b8bc3ef..6ffccfce0832 100644 --- a/apps/meteor/server/sdk/index.ts +++ b/apps/meteor/server/sdk/index.ts @@ -20,6 +20,7 @@ import type { IVideoConfService } from './types/IVideoConfService'; import type { ISAUMonitorService } from './types/ISAUMonitorService'; import type { IDeviceManagementService } from './types/IDeviceManagementService'; import { FibersContextStore } from './lib/ContextStore'; +import type { IUploadService } from './types/IUploadService'; // TODO think in a way to not have to pass the service name to proxify here as well export const Authorization = proxifyWithWait('authorization'); @@ -40,7 +41,7 @@ export const LDAP = proxifyWithWait('ldap'); export const SAUMonitor = proxifyWithWait('sau-monitor'); export const DeviceManagement = proxifyWithWait('device-management'); export const VideoConf = proxifyWithWait('video-conference'); - +export const Upload = proxifyWithWait('upload'); // Calls without wait. Means that the service is optional and the result may be an error // of service/method not available export const EnterpriseSettings = proxify('ee-settings'); diff --git a/apps/meteor/server/sdk/types/IUploadService.ts b/apps/meteor/server/sdk/types/IUploadService.ts new file mode 100644 index 000000000000..641189355bb0 --- /dev/null +++ b/apps/meteor/server/sdk/types/IUploadService.ts @@ -0,0 +1,27 @@ +import type { IUploadDetails } from '@rocket.chat/apps-engine/definition/uploads/IUploadDetails'; +import type { IMessage, IUpload } from '@rocket.chat/core-typings'; + +export interface IUploadFileParams { + userId: string; + buffer: Buffer; + details: Partial; +} +export interface ISendFileMessageParams { + roomId: string; + userId: string; + file: IUpload; + message?: IMessage; +} + +export interface ISendFileLivechatMessageParams { + roomId: string; + visitorToken: string; + file: IUpload; + message?: IMessage; +} + +export interface IUploadService { + uploadFile(params: IUploadFileParams): Promise; + sendFileMessage(params: ISendFileMessageParams): Promise; + sendFileLivechatMessage(params: ISendFileLivechatMessageParams): Promise; +} diff --git a/apps/meteor/server/services/startup.ts b/apps/meteor/server/services/startup.ts index c2aab2335b9b..90ac1e9ed834 100644 --- a/apps/meteor/server/services/startup.ts +++ b/apps/meteor/server/services/startup.ts @@ -21,6 +21,7 @@ import { isRunningMs } from '../lib/isRunningMs'; import { PushService } from './push/service'; import { DeviceManagementService } from './device-management/service'; import { FederationService } from './federation/service'; +import { UploadService } from './upload/service'; const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo; @@ -43,6 +44,7 @@ api.registerService(new PushService()); api.registerService(new DeviceManagementService()); api.registerService(new VideoConfService()); api.registerService(new FederationService()); +api.registerService(new UploadService()); // if the process is running in micro services mode we don't need to register services that will run separately if (!isRunningMs()) { diff --git a/apps/meteor/server/services/upload/service.ts b/apps/meteor/server/services/upload/service.ts new file mode 100644 index 000000000000..3bdc910ee80c --- /dev/null +++ b/apps/meteor/server/services/upload/service.ts @@ -0,0 +1,39 @@ +import type { IMessage, IUpload } from '@rocket.chat/core-typings'; +import { Meteor } from 'meteor/meteor'; + +import { ServiceClassInternal } from '../../sdk/types/ServiceClass'; +import type { + ISendFileLivechatMessageParams, + ISendFileMessageParams, + IUploadFileParams, + IUploadService, +} from '../../sdk/types/IUploadService'; +import { FileUpload } from '../../../app/file-upload/server'; + +export class UploadService extends ServiceClassInternal implements IUploadService { + protected name = 'upload'; + + async uploadFile({ buffer, details }: IUploadFileParams): Promise { + const fileStore = FileUpload.getStore('Uploads'); + return fileStore.insert(details, buffer); + } + + async sendFileMessage({ roomId, file, userId, message }: ISendFileMessageParams): Promise { + return Meteor.runAsUser(userId, () => Meteor.call('sendFileMessage', roomId, null, file, message)); + } + + async sendFileLivechatMessage({ roomId, visitorToken, file, message }: ISendFileLivechatMessageParams): Promise { + return Meteor.call('sendFileLivechatMessage', roomId, visitorToken, file, message); + } + + async getFileBuffer({ file }: { userId: string; file: IUpload }): Promise { + return new Promise((resolve, reject) => { + FileUpload.getBuffer(file, (err: Error, buffer: Buffer) => { + if (err) { + return reject(err); + } + return resolve(buffer); + }); + }); + } +}