refactor: Remove wrapAsync (#28825)

Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com>
pull/29082/head
Rodrigo Nascimento 3 years ago committed by GitHub
parent 94c9050cea
commit 20b0976fbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      apps/meteor/app/apps/server/bridges/uploads.ts
  2. 2
      apps/meteor/app/federation/server/endpoints/uploads.js
  3. 2
      apps/meteor/app/federation/server/lib/crypt.js
  4. 18
      apps/meteor/app/federation/server/lib/dns.js
  5. 14
      apps/meteor/app/file-upload/server/config/FileSystem.ts
  6. 22
      apps/meteor/app/file-upload/server/lib/FileUpload.ts
  7. 11
      apps/meteor/app/importer-pending-files/server/importer.js
  8. 5
      apps/meteor/app/integrations/server/api/api.js
  9. 5
      apps/meteor/app/integrations/server/lib/triggerHandler.js
  10. 2
      apps/meteor/app/lib/server/functions/saveUser.js
  11. 2
      apps/meteor/app/lib/server/functions/setEmail.ts
  12. 7
      apps/meteor/app/lib/server/lib/validateEmailDomain.js
  13. 5
      apps/meteor/app/livechat/server/lib/Livechat.js
  14. 28
      apps/meteor/app/meteor-accounts-saml/server/lib/SAML.ts
  15. 96
      apps/meteor/app/meteor-accounts-saml/server/lib/ServiceProvider.ts
  16. 4
      apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts
  17. 51
      apps/meteor/server/features/EmailInbox/EmailInbox_Outgoing.ts
  18. 38
      apps/meteor/server/lib/http/call.ts
  19. 1
      apps/meteor/server/main.ts
  20. 2
      apps/meteor/server/methods/registerUser.ts
  21. 7
      apps/meteor/server/overrides/http.ts
  22. 20
      apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/File.ts
  23. 19
      apps/meteor/server/services/upload/service.ts

@ -31,19 +31,13 @@ export class AppUploadBridge extends UploadBridge {
const rocketChatUpload = this.orch.getConverters()?.get('uploads').convertToRocketChat(upload);
return new Promise((resolve, reject) => {
FileUpload.getBuffer(rocketChatUpload, (error?: Error, result?: Buffer | false) => {
if (error) {
return reject(error);
}
const result = await FileUpload.getBuffer(rocketChatUpload);
if (!(result instanceof Buffer)) {
return reject(new Error('Unknown error'));
}
if (!(result instanceof Buffer)) {
throw new Error('Unknown error');
}
resolve(result);
});
});
return result;
}
protected async createUpload(details: IUploadDetails, buffer: Buffer, appId: string): Promise<IUpload> {

@ -21,7 +21,7 @@ API.v1.addRoute(
return API.v1.failure('There is no such file in this server');
}
const buffer = FileUpload.getBufferSync(upload);
const buffer = await FileUpload.getBuffer(upload);
return API.v1.success({ upload, buffer });
},

@ -40,7 +40,7 @@ export async function decryptIfNeeded(request, bodyParams) {
}
//
// Find the peer's public key
const { publicKey: peerKey } = search(remotePeerDomain);
const { publicKey: peerKey } = await search(remotePeerDomain);
if (!peerKey) {
throw new Error("Could not find the peer's public key to decrypt");

@ -1,6 +1,6 @@
import dnsResolver from 'dns';
import util from 'util';
import { Meteor } from 'meteor/meteor';
import mem from 'mem';
import * as federationErrors from '../functions/errors';
@ -8,8 +8,8 @@ import { dnsLogger } from './logger';
import { isFederationEnabled } from './isFederationEnabled';
import { federationRequest } from './http';
const dnsResolveSRV = Meteor.wrapAsync(dnsResolver.resolveSrv);
const dnsResolveTXT = Meteor.wrapAsync(dnsResolver.resolveTxt);
const dnsResolveSRV = util.promisify(dnsResolver.resolveSrv);
const dnsResolveTXT = util.promisify(dnsResolver.resolveTxt);
const cacheMaxAge = 3600000; // one hour
const memoizedDnsResolveSRV = mem(dnsResolveSRV, { maxAge: cacheMaxAge });
@ -62,7 +62,7 @@ async function searchHub(peerDomain) {
}
}
export function search(peerDomain) {
export async function search(peerDomain) {
if (!isFederationEnabled()) {
throw federationErrors.disabled('dns.search');
}
@ -75,7 +75,7 @@ export function search(peerDomain) {
// Search by HTTPS first
try {
dnsLogger.debug(`search: peerDomain=${peerDomain} srv=_rocketchat._https.${peerDomain}`);
srvEntries = memoizedDnsResolveSRV(`_rocketchat._https.${peerDomain}`);
srvEntries = await memoizedDnsResolveSRV(`_rocketchat._https.${peerDomain}`);
protocol = 'https';
} catch (err) {
// Ignore errors when looking for DNS entries
@ -85,7 +85,7 @@ export function search(peerDomain) {
if (!srvEntries.length) {
try {
dnsLogger.debug(`search: peerDomain=${peerDomain} srv=_rocketchat._http.${peerDomain}`);
srvEntries = memoizedDnsResolveSRV(`_rocketchat._http.${peerDomain}`);
srvEntries = await memoizedDnsResolveSRV(`_rocketchat._http.${peerDomain}`);
protocol = 'http';
} catch (err) {
// Ignore errors when looking for DNS entries
@ -96,12 +96,12 @@ export function search(peerDomain) {
if (!srvEntries.length) {
try {
dnsLogger.debug(`search: peerDomain=${peerDomain} srv=_rocketchat._tcp.${peerDomain}`);
srvEntries = memoizedDnsResolveSRV(`_rocketchat._tcp.${peerDomain}`);
srvEntries = await memoizedDnsResolveSRV(`_rocketchat._tcp.${peerDomain}`);
protocol = 'https'; // https is the default
// Then, also try to get the protocol
dnsLogger.debug(`search: peerDomain=${peerDomain} txt=rocketchat-tcp-protocol.${peerDomain}`);
protocol = memoizedDnsResolveSRV(`rocketchat-tcp-protocol.${peerDomain}`);
protocol = await memoizedDnsResolveSRV(`rocketchat-tcp-protocol.${peerDomain}`);
protocol = protocol[0].join('');
if (protocol !== 'http' && protocol !== 'https') {
@ -131,7 +131,7 @@ export function search(peerDomain) {
// Get the public key from the TXT record
try {
dnsLogger.debug(`search: peerDomain=${peerDomain} txt=rocketchat-public-key.${peerDomain}`);
const publicKeyTxtRecords = memoizedDnsResolveTXT(`rocketchat-public-key.${peerDomain}`);
const publicKeyTxtRecords = await memoizedDnsResolveTXT(`rocketchat-public-key.${peerDomain}`);
// Join the TXT record, that might be split
publicKey = publicKeyTxtRecords[0].join('');

@ -1,14 +1,10 @@
import fs from 'fs';
import { Meteor } from 'meteor/meteor';
import fsp from 'fs/promises';
import { UploadFS } from '../../../../server/ufs';
import { settings } from '../../../settings/server';
import { FileUploadClass, FileUpload } from '../lib/FileUpload';
import { getFileRange, setRangeHeaders } from '../lib/ranges';
const statSync = Meteor.wrapAsync(fs.stat);
const FileSystemUploads = new FileUploadClass({
name: 'FileSystem:Uploads',
// store setted bellow
@ -22,7 +18,7 @@ const FileSystemUploads = new FileUploadClass({
const options: { start?: number; end?: number } = {};
try {
const stat = statSync(filePath);
const stat = await fsp.stat(filePath);
if (!stat?.isFile()) {
res.writeHead(404);
res.end();
@ -65,7 +61,7 @@ const FileSystemUploads = new FileUploadClass({
}
const filePath = await this.store.getFilePath(file._id, file);
try {
const stat = statSync(filePath);
const stat = await fsp.stat(filePath);
if (stat?.isFile()) {
file = FileUpload.addExtensionTo(file);
@ -89,7 +85,7 @@ const FileSystemAvatars = new FileUploadClass({
const filePath = await this.store.getFilePath(file._id, file);
try {
const stat = statSync(filePath);
const stat = await fsp.stat(filePath);
if (stat?.isFile()) {
file = FileUpload.addExtensionTo(file);
@ -113,7 +109,7 @@ const FileSystemUserDataFiles = new FileUploadClass({
const filePath = await this.store.getFilePath(file._id, file);
try {
const stat = statSync(filePath);
const stat = await fsp.stat(filePath);
if (stat?.isFile()) {
file = FileUpload.addExtensionTo(file);

@ -290,7 +290,7 @@ export const FileUpload = {
},
async extractMetadata(file: IUpload) {
return sharp(FileUpload.getBufferSync(file)).metadata();
return sharp(await FileUpload.getBuffer(file)).metadata();
},
async createImageThumbnail(fileParam: IUpload) {
@ -508,26 +508,30 @@ export const FileUpload = {
res.end();
},
getBuffer(file: IUpload, cb: (err?: Error, data?: false | Buffer) => void) {
async getBuffer(file: IUpload): Promise<Buffer> {
const store = this.getStoreByName(file.store);
if (!store?.get) {
cb(new Error('Store is invalid'), undefined);
throw new Error('Store is invalid');
}
const buffer = new streamBuffers.WritableStreamBuffer({
initialSize: file.size,
});
buffer.on('finish', () => {
cb(undefined, buffer.getContents());
});
return new Promise((resolve, reject) => {
buffer.on('finish', () => {
const contents = buffer.getContents();
if (contents === false) {
return reject();
}
resolve(contents);
});
void store.copy?.(file, buffer);
void store.copy?.(file, buffer);
});
},
getBufferSync: Meteor.wrapAsync((file: IUpload, cb: (err?: Error, data?: false | Buffer) => void) => FileUpload.getBuffer(file, cb)),
async copy(file: IUpload, targetFile: string) {
const store = this.getStoreByName(file.store);
const out = fs.createWriteStream(targetFile);

@ -1,7 +1,6 @@
import https from 'https';
import http from 'http';
import { Meteor } from 'meteor/meteor';
import { Random } from '@rocket.chat/random';
import { Messages } from '@rocket.chat/models';
@ -48,12 +47,12 @@ export class PendingFileImporter extends Base {
let currentSize = 0;
let nextSize = 0;
const waitForFiles = () => {
const waitForFiles = async () => {
if (count + 1 < maxFileCount && currentSize + nextSize < maxFileSize) {
return;
}
Meteor.wrapAsync((callback) => {
return new Promise((resolve) => {
const handler = setInterval(() => {
if (count + 1 >= maxFileCount) {
return;
@ -64,9 +63,9 @@ export class PendingFileImporter extends Base {
}
clearInterval(handler);
callback();
resolve();
}, 1000);
})();
});
};
const completeFile = async (details) => {
@ -109,7 +108,7 @@ export class PendingFileImporter extends Base {
const reportProgress = this.reportProgress.bind(this);
nextSize = details.size;
waitForFiles();
await waitForFiles();
count++;
currentSize += nextSize;
downloadedFileIds.push(_importFile.id);

@ -1,6 +1,5 @@
import { VM, VMScript } from 'vm2';
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
import { Random } from '@rocket.chat/random';
import { Livechat } from 'meteor/rocketchat:livechat';
import Fiber from 'fibers';
@ -15,6 +14,7 @@ import { incomingLogger } from '../logger';
import { processWebhookMessage } from '../../../lib/server/functions/processWebhookMessage';
import { API, APIClass, defaultRateLimiterOptions } from '../../../api/server';
import { settings } from '../../../settings/server';
import { httpCall } from '../../../../server/lib/http/call';
import { deleteOutgoingIntegration } from '../methods/outgoing/deleteOutgoingIntegration';
export const forbiddenModelMethods = ['registerModel', 'getCollectionName'];
@ -43,8 +43,9 @@ function buildSandbox(store = {}) {
},
HTTP(method, url, options) {
try {
// Need to review how we will handle this, possible breaking change on removing fibers
return {
result: HTTP.call(method, url, options),
result: Promise.await(httpCall(method, url, options)),
};
} catch (error) {
return {

@ -1,7 +1,6 @@
import { VM, VMScript } from 'vm2';
import { Meteor } from 'meteor/meteor';
import { Random } from '@rocket.chat/random';
import { HTTP } from 'meteor/http';
import _ from 'underscore';
import moment from 'moment';
import Fiber from 'fibers';
@ -18,6 +17,7 @@ import { outgoingLogger } from '../logger';
import { outgoingEvents } from '../../lib/outgoingEvents';
import { omit } from '../../../../lib/utils/omit';
import { forbiddenModelMethods } from '../api/api';
import { httpCall } from '../../../../server/lib/http/call';
class RocketChatIntegrationHandler {
constructor() {
@ -247,8 +247,9 @@ class RocketChatIntegrationHandler {
},
HTTP: (method, url, options) => {
try {
// Need to review how we will handle this, possible breaking change on removing fibers
return {
result: HTTP.call(method, url, options),
result: Promise.await(httpCall(method, url, options)),
};
} catch (error) {
return { error };

@ -266,7 +266,7 @@ const handleNickname = (updateUser, nickname) => {
};
const saveNewUser = async function (userData, sendPassword) {
validateEmailDomain(userData.email);
await validateEmailDomain(userData.email);
const roles = (!!userData.roles && userData.roles.length > 0 && userData.roles) || getNewUserRoles();
const isGuest = roles && roles.length === 1 && roles.includes('guest');

@ -47,7 +47,7 @@ const _setEmail = async function (userId: string, email: string, shouldSendVerif
throw new Meteor.Error('error-invalid-email', 'Invalid email', { function: '_setEmail' });
}
validateEmailDomain(email);
await validateEmailDomain(email);
const user = await Users.findOneById(userId);
if (!user) {

@ -1,4 +1,5 @@
import dns from 'dns';
import util from 'util';
import { Meteor } from 'meteor/meteor';
@ -6,7 +7,7 @@ import { emailDomainDefaultBlackList } from './defaultBlockedDomainsList';
import { settings } from '../../../settings/server';
import { validateEmail } from '../../../../lib/emailValidator';
const dnsResolveMx = Meteor.wrapAsync(dns.resolveMx);
const dnsResolveMx = util.promisify(dns.resolveMx);
let emailDomainBlackList = [];
let emailDomainWhiteList = [];
@ -34,7 +35,7 @@ settings.watch('Accounts_AllowedDomainsList', function (value) {
.map((domain) => domain.trim());
});
export const validateEmailDomain = function (email) {
export const validateEmailDomain = async function (email) {
if (!validateEmail(email)) {
throw new Meteor.Error('error-invalid-email', `Invalid email ${email}`, {
function: 'RocketChat.validateEmailDomain',
@ -61,7 +62,7 @@ export const validateEmailDomain = function (email) {
if (settings.get('Accounts_UseDNSDomainCheck')) {
try {
dnsResolveMx(emailDomain);
await dnsResolveMx(emailDomain);
} catch (e) {
throw new Meteor.Error('error-invalid-domain', 'Invalid domain', {
function: 'RocketChat.validateEmailDomain',

@ -2,6 +2,7 @@
// Please add new methods to LivechatTyped.ts
import dns from 'dns';
import util from 'util';
import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';
@ -47,7 +48,7 @@ import { Livechat as LivechatTyped } from './LivechatTyped';
const logger = new Logger('Livechat');
const dnsResolveMx = Meteor.wrapAsync(dns.resolveMx);
const dnsResolveMx = util.promisify(dns.resolveMx);
export const Livechat = {
Analytics,
@ -1183,7 +1184,7 @@ export const Livechat = {
const emailDomain = email.substr(email.lastIndexOf('@') + 1);
try {
dnsResolveMx(emailDomain);
await dnsResolveMx(emailDomain);
} catch (e) {
throw new Meteor.Error('error-invalid-email-address', 'Invalid email address', {
method: 'livechat:sendOfflineMessage',

@ -374,22 +374,28 @@ export class SAML {
res.end();
}
private static processAuthorizeAction(res: ServerResponse, service: IServiceProviderOptions, samlObject: ISAMLAction): void {
private static async processAuthorizeAction(
res: ServerResponse,
service: IServiceProviderOptions,
samlObject: ISAMLAction,
): Promise<void> {
service.id = samlObject.credentialToken;
const serviceProvider = new SAMLServiceProvider(service);
serviceProvider.getAuthorizeUrl((err, url) => {
if (err) {
SAMLUtils.error('Unable to generate authorize url');
SAMLUtils.error(err);
url = Meteor.absoluteUrl();
}
let url: string | undefined;
res.writeHead(302, {
Location: url,
});
res.end();
try {
url = await serviceProvider.getAuthorizeUrl();
} catch (err: any) {
SAMLUtils.error('Unable to generate authorize url');
SAMLUtils.error(err);
url = Meteor.absoluteUrl();
}
res.writeHead(302, {
Location: url,
});
res.end();
}
private static processValidateAction(

@ -1,6 +1,7 @@
import zlib from 'zlib';
import crypto from 'crypto';
import querystring from 'querystring';
import util from 'util';
import { Meteor } from 'meteor/meteor';
@ -20,18 +21,12 @@ import type { ILogoutRequestValidateCallback, ILogoutResponseValidateCallback, I
export class SAMLServiceProvider {
serviceProviderOptions: IServiceProviderOptions;
syncRequestToUrl: Function;
constructor(serviceProviderOptions: IServiceProviderOptions) {
if (!serviceProviderOptions) {
throw new Error('SAMLServiceProvider instantiated without an options object');
}
this.serviceProviderOptions = serviceProviderOptions;
this.syncRequestToUrl = Meteor.wrapAsync<
(request: string, operation: string, callback: (err: string | object | null, url?: string | undefined) => void) => void
>(this.requestToUrl, this);
}
private signRequest(xml: string): string {
@ -105,68 +100,63 @@ export class SAMLServiceProvider {
/*
This method will generate the request URL with all the query string params and pass it to the callback
*/
public requestToUrl(request: string, operation: string, callback: (err: string | object | null, url?: string) => void): void {
zlib.deflateRaw(request, (err, buffer) => {
if (err) {
return callback(err);
}
try {
const base64 = buffer.toString('base64');
let target = this.serviceProviderOptions.entryPoint;
if (operation === 'logout') {
if (this.serviceProviderOptions.idpSLORedirectURL) {
target = this.serviceProviderOptions.idpSLORedirectURL;
}
public async requestToUrl(request: string, operation: string): Promise<string | undefined> {
const buffer = await util.promisify(zlib.deflateRaw)(request);
try {
const base64 = buffer.toString('base64');
let target = this.serviceProviderOptions.entryPoint;
if (operation === 'logout') {
if (this.serviceProviderOptions.idpSLORedirectURL) {
target = this.serviceProviderOptions.idpSLORedirectURL;
}
}
if (target.indexOf('?') > 0) {
target += '&';
} else {
target += '?';
}
if (target.indexOf('?') > 0) {
target += '&';
} else {
target += '?';
}
// TBD. We should really include a proper RelayState here
let relayState;
if (operation === 'logout') {
// in case of logout we want to be redirected back to the Meteor app.
relayState = Meteor.absoluteUrl();
} else {
relayState = this.serviceProviderOptions.provider;
}
// TBD. We should really include a proper RelayState here
let relayState;
if (operation === 'logout') {
// in case of logout we want to be redirected back to the Meteor app.
relayState = Meteor.absoluteUrl();
} else {
relayState = this.serviceProviderOptions.provider;
}
const samlRequest: Record<string, any> = {
SAMLRequest: base64,
RelayState: relayState,
};
const samlRequest: Record<string, any> = {
SAMLRequest: base64,
RelayState: relayState,
};
if (this.serviceProviderOptions.privateCert) {
samlRequest.SigAlg = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
samlRequest.Signature = this.signRequest(querystring.stringify(samlRequest));
}
if (this.serviceProviderOptions.privateCert) {
samlRequest.SigAlg = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
samlRequest.Signature = this.signRequest(querystring.stringify(samlRequest));
}
target += querystring.stringify(samlRequest);
target += querystring.stringify(samlRequest);
SAMLUtils.log(`requestToUrl: ${target}`);
SAMLUtils.log(`requestToUrl: ${target}`);
if (operation === 'logout') {
// in case of logout we want to be redirected back to the Meteor app.
return callback(null, target);
}
callback(null, target);
} catch (error) {
callback(error instanceof Error ? error : String(error));
if (operation === 'logout') {
// in case of logout we want to be redirected back to the Meteor app.
return target;
}
});
return target;
} catch (error) {
throw error instanceof Error ? error : String(error);
}
}
public getAuthorizeUrl(callback: (err: string | object | null, url?: string) => void): void {
public async getAuthorizeUrl(): Promise<string | undefined> {
const request = this.generateAuthorizeRequest();
SAMLUtils.log('-----REQUEST------');
SAMLUtils.log(request);
this.requestToUrl(request, 'authorize', callback);
return this.requestToUrl(request, 'authorize');
}
public async validateLogoutRequest(samlRequest: string, callback: ILogoutRequestValidateCallback): Promise<void> {

@ -28,7 +28,7 @@ function getSamlServiceProviderOptions(provider: string): IServiceProviderOption
declare module '@rocket.chat/ui-contexts' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface ServerMethods {
samlLogout(provider: string): Promise<void>;
samlLogout(provider: string): Promise<string | undefined>;
}
}
@ -71,7 +71,7 @@ Meteor.methods<ServerMethods>({
await Users.setSamlInResponseTo(userId, request.id);
const result = _saml.syncRequestToUrl(request.request, 'logout');
const result = await _saml.requestToUrl(request.request, 'logout');
SAMLUtils.log(`SAML Logout Request ${result}`);
return result;

@ -124,32 +124,31 @@ slashCommands.add({
return;
}
FileUpload.getBuffer(file, (_err?: Error, buffer?: Buffer | false) => {
!_err &&
buffer &&
void sendEmail(
inbox,
{
to: room.email?.replyTo,
subject: room.email?.subject,
text: message?.attachments?.[0].description || '',
attachments: [
{
content: buffer,
contentType: file.type,
filename: file.name,
},
],
inReplyTo: Array.isArray(room.email?.thread) ? room.email?.thread[0] : room.email?.thread,
references: ([] as string[]).concat(room.email?.thread || []),
},
{
msgId: message._id,
sender: message.u.username,
rid: message.rid,
},
).then((info) => LivechatRooms.updateEmailThreadByRoomId(room._id, info.messageId));
});
const buffer = await FileUpload.getBuffer(file);
if (buffer) {
void sendEmail(
inbox,
{
to: room.email?.replyTo,
subject: room.email?.subject,
text: message?.attachments?.[0].description || '',
attachments: [
{
content: buffer,
contentType: file.type,
filename: file.name,
},
],
inReplyTo: Array.isArray(room.email?.thread) ? room.email?.thread[0] : room.email?.thread,
references: ([] as string[]).concat(room.email?.thread || []),
},
{
msgId: message._id,
sender: message.u.username,
rid: message.rid,
},
).then((info) => LivechatRooms.updateEmailThreadByRoomId(room._id, info.messageId));
}
await Messages.updateOne(
{ _id: message._id },

@ -1,4 +1,4 @@
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
import { URL, URLSearchParams } from 'meteor/url';
import { serverFetch as fetch } from '@rocket.chat/server-fetch';
@ -25,10 +25,17 @@ type HttpCallOptions = {
integrity?: string;
};
type callbackFn = {
(error: unknown): void;
(error: unknown, result: unknown): void;
};
// eslint-disable-next-line @typescript-eslint/naming-convention
interface HTTPResponse {
statusCode?: number;
headers?: { [id: string]: string };
content?: string;
data?: any;
ok?: boolean;
redirected?: boolean;
}
type callbackFn = (error: Error | undefined, result?: HTTPResponse) => void;
// Fill in `response.data` if the content-type is JSON.
function populateData(response: Record<string, any>): void {
@ -49,7 +56,7 @@ function populateData(response: Record<string, any>): void {
}
}
function makeErrorByStatus(statusCode: string, content: string): Error {
function makeErrorByStatus(statusCode: number, content: string): Error {
let message = `failed [${statusCode}]`;
if (content) {
@ -117,9 +124,9 @@ function _call(httpMethod: string, url: string, options: HttpCallOptions, callba
// wrap callback to add a 'response' property on an error, in case
// we have both (http 4xx/5xx error, which has a response payload)
const wrappedCallback = ((cb: callbackFn): { (error: unknown, response?: unknown): void } => {
const wrappedCallback = ((cb: callbackFn): { (error: Error | undefined, response?: HTTPResponse): void } => {
let called = false;
return (error: unknown, response: unknown): void => {
return (error: Error | undefined, response?: HTTPResponse): void => {
if (!called) {
called = true;
if (error && response) {
@ -147,7 +154,7 @@ function _call(httpMethod: string, url: string, options: HttpCallOptions, callba
fetch(newUrl, requestOptions)
.then(async (res) => {
const content = await res.text();
const response: Record<string, any> = {};
const response: HTTPResponse = {};
response.statusCode = res.status;
response.content = `${content}`;
@ -177,7 +184,7 @@ function _call(httpMethod: string, url: string, options: HttpCallOptions, callba
function httpCallAsync(httpMethod: string, url: string, options: HttpCallOptions, callback: callbackFn): void;
function httpCallAsync(httpMethod: string, url: string, callback: callbackFn): void;
function httpCallAsync(httpMethod: string, url: string, optionsOrCallback: HttpCallOptions | callbackFn = {}, callback?: callbackFn): void {
// If the options argument was ommited, adjust the arguments:
// If the options argument was omitted, adjust the arguments:
if (!callback && typeof optionsOrCallback === 'function') {
return _call(httpMethod, url, {}, optionsOrCallback as callbackFn);
}
@ -185,4 +192,13 @@ function httpCallAsync(httpMethod: string, url: string, optionsOrCallback: HttpC
return _call(httpMethod, url, optionsOrCallback as HttpCallOptions, callback as callbackFn);
}
export const httpCall = Meteor.wrapAsync(httpCallAsync);
export const httpCall = async (httpMethod: string, url: string, options: HttpCallOptions) => {
return new Promise((resolve, reject) => {
httpCallAsync.bind(HTTP)(httpMethod, url, options, (error, result) => {
if (error) {
return reject(error);
}
resolve(result);
});
});
};

@ -4,7 +4,6 @@ import '../ee/server/models/startup';
import './services/startup';
import '../app/settings/server';
import '../lib/oauthRedirectUriServer';
import './overrides/http';
import './lib/logger/startup';
import './importPackages';
import '../imports/startup/server';

@ -84,7 +84,7 @@ Meteor.methods<ServerMethods>({
passwordPolicy.validate(formData.pass);
validateEmailDomain(formData.email);
await validateEmailDomain(formData.email);
const userData = {
email: trim(formData.email.toLowerCase()),

@ -1,7 +0,0 @@
import { HTTP } from 'meteor/http';
import { httpCall } from '../lib/http/call';
HTTP.call = function _call(...args: Parameters<typeof HTTP.call>): ReturnType<typeof HTTP.call> {
return httpCall.call(HTTP, ...args);
};

@ -34,17 +34,11 @@ export class RocketChatFileAdapter {
}
public async getBufferFromFileRecord(fileRecord: IUpload): Promise<Buffer> {
return new Promise((resolve, reject) => {
FileUpload.getBuffer(fileRecord, (err?: Error, buffer?: Buffer | false) => {
if (err) {
return reject(err);
}
if (!(buffer instanceof Buffer)) {
return reject(new Error('Unknown error'));
}
resolve(buffer);
});
});
const buffer = await FileUpload.getBuffer(fileRecord);
if (!(buffer instanceof Buffer)) {
throw new Error('Unknown error');
}
return buffer;
}
public async getFileRecordById(fileId: string): Promise<IUpload | undefined | null> {
@ -71,11 +65,11 @@ export class RocketChatFileAdapter {
}
public async getBufferForAvatarFile(username: string): Promise<any> {
const file = (await Avatars.findOneByName(username)) as Record<string, any>;
const file = await Avatars.findOneByName(username);
if (!file?._id) {
return;
}
return FileUpload.getBufferSync(file);
return FileUpload.getBuffer(file);
}
public async getFileMetadataForAvatarFile(username: string): Promise<IAvatarMetadataFile> {

@ -24,18 +24,13 @@ export class UploadService extends ServiceClassInternal implements IUploadServic
}
async getFileBuffer({ userId, file }: { userId: string; file: IUpload }): Promise<Buffer> {
return Meteor.runAsUser(userId, () => {
return new Promise((resolve, reject) => {
FileUpload.getBuffer(file, (err?: Error, buffer?: false | Buffer) => {
if (err) {
return reject(err);
}
if (!(buffer instanceof Buffer)) {
return reject(new Error('Unknown error'));
}
return resolve(buffer);
});
});
return Meteor.runAsUser(userId, async () => {
const buffer = await FileUpload.getBuffer(file);
if (!(buffer instanceof Buffer)) {
throw new Error('Unknown error');
}
return buffer;
});
}
}

Loading…
Cancel
Save