Skip to content

Commit

Permalink
Merge branch 'develop' into fix-login-with-rest-disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] committed May 31, 2024
2 parents de1960f + 8e4485b commit 770ade3
Show file tree
Hide file tree
Showing 47 changed files with 832 additions and 580 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-onions-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

When using `DISABLE_DB_WATCHERS=true` this fixes message updates with URLs that were missing the link preview.
5 changes: 5 additions & 0 deletions .changeset/rare-colts-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes an issue not rendering the proper error and empty state on users in role table
5 changes: 5 additions & 0 deletions .changeset/sweet-kiwis-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": minor
---

Clicking on a message attachment link in the Desktop App will now initiate a direct download of the attachment only when the attachment is not a PDF file
4 changes: 2 additions & 2 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ jobs:
steps:
- uses: actions/stale@v5
with:
days-before-issue-stale: 10
days-before-issue-close: 4
days-before-issue-stale: 14
days-before-issue-close: 14
any-of-labels: 'stat: need more info,stat: waiting response'
stale-issue-label: "stat: no response"
stale-issue-message: "This issue has been marked as stale because there has been no further activity in the last 10 days. If the issue remains stale for the next 4 days (a total of 14 days with no activity), then it will be assumed that the question has been resolved and the issue will be automatically closed."
Expand Down
52 changes: 38 additions & 14 deletions apps/meteor/app/api/server/lib/emailInbox.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { IEmailInbox } from '@rocket.chat/core-typings';
import { EmailInbox, Users } from '@rocket.chat/models';
import type { Filter, InsertOneResult, Sort, UpdateResult, WithId } from 'mongodb';
import type { DeleteResult, Filter, InsertOneResult, Sort } from 'mongodb';

import { notifyOnEmailInboxChanged } from '../../../lib/server/lib/notifyListener';

export const findEmailInboxes = async ({
query = {},
Expand Down Expand Up @@ -34,33 +36,31 @@ export const findEmailInboxes = async ({
};
};

export const findOneEmailInbox = async ({ _id }: { _id: string }): Promise<IEmailInbox | null> => {
return EmailInbox.findOneById(_id);
};
export const insertOneEmailInbox = async (
userId: string,
emailInboxParams: Pick<IEmailInbox, 'active' | 'name' | 'email' | 'description' | 'senderInfo' | 'department' | 'smtp' | 'imap'>,
): Promise<InsertOneResult<WithId<IEmailInbox>>> => {
): Promise<InsertOneResult<IEmailInbox>> => {
const obj = {
...emailInboxParams,
_createdAt: new Date(),
_updatedAt: new Date(),
_createdBy: await Users.findOneById(userId, { projection: { username: 1 } }),
};
return EmailInbox.insertOne(obj);

const response = await EmailInbox.create(obj);

if (response.insertedId) {
void notifyOnEmailInboxChanged({ _id: response.insertedId, ...obj }, 'inserted');
}

return response;
};

export const updateEmailInbox = async (
emailInboxParams: Pick<IEmailInbox, '_id' | 'active' | 'name' | 'email' | 'description' | 'senderInfo' | 'department' | 'smtp' | 'imap'>,
): Promise<InsertOneResult<WithId<IEmailInbox>> | UpdateResult> => {
): Promise<Pick<IEmailInbox, '_id'> | null> => {
const { _id, active, name, email, description, senderInfo, department, smtp, imap } = emailInboxParams;

const emailInbox = await findOneEmailInbox({ _id });

if (!emailInbox) {
throw new Error('error-invalid-email-inbox');
}

const updateEmailInbox = {
$set: {
active,
Expand All @@ -76,5 +76,29 @@ export const updateEmailInbox = async (
...(department === 'All' && { $unset: { department: 1 as const } }),
};

return EmailInbox.updateOne({ _id }, updateEmailInbox);
const updatedResponse = await EmailInbox.updateById(_id, updateEmailInbox);

if (!updatedResponse.value) {
throw new Error('error-invalid-email-inbox');
}

void notifyOnEmailInboxChanged(
{
...updatedResponse.value,
...(department === 'All' && { department: undefined }),
},
'updated',
);

return updatedResponse.value;
};

export const removeEmailInbox = async (emailInboxId: IEmailInbox['_id']): Promise<DeleteResult> => {
const removeResponse = await EmailInbox.removeById(emailInboxId);

if (removeResponse.deletedCount) {
void notifyOnEmailInboxChanged({ _id: emailInboxId }, 'removed');
}

return removeResponse;
};
34 changes: 23 additions & 11 deletions apps/meteor/app/api/server/v1/email-inbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { check, Match } from 'meteor/check';
import { sendTestEmailToInbox } from '../../../../server/features/EmailInbox/EmailInbox_Outgoing';
import { API } from '../api';
import { getPaginationItems } from '../helpers/getPaginationItems';
import { insertOneEmailInbox, findEmailInboxes, findOneEmailInbox, updateEmailInbox } from '../lib/emailInbox';
import { insertOneEmailInbox, findEmailInboxes, updateEmailInbox, removeEmailInbox } from '../lib/emailInbox';

API.v1.addRoute(
'email-inbox.list',
Expand Down Expand Up @@ -55,12 +55,23 @@ API.v1.addRoute(
let _id: string;

if (!emailInboxParams?._id) {
const emailInbox = await insertOneEmailInbox(this.userId, emailInboxParams);
_id = emailInbox.insertedId.toString();
const { insertedId } = await insertOneEmailInbox(this.userId, emailInboxParams);

if (!insertedId) {
return API.v1.failure('Failed to create email inbox');
}

_id = insertedId;
} else {
_id = emailInboxParams._id;
await updateEmailInbox({ ...emailInboxParams, _id });
const emailInbox = await updateEmailInbox({ ...emailInboxParams, _id: emailInboxParams._id });

if (!emailInbox?._id) {
return API.v1.failure('Failed to update email inbox');
}

_id = emailInbox._id;
}

return API.v1.success({ _id });
},
},
Expand All @@ -79,7 +90,7 @@ API.v1.addRoute(
if (!_id) {
throw new Error('error-invalid-param');
}
const emailInbox = await findOneEmailInbox({ _id });
const emailInbox = await EmailInbox.findOneById(_id);

if (!emailInbox) {
return API.v1.notFound();
Expand All @@ -97,11 +108,12 @@ API.v1.addRoute(
throw new Error('error-invalid-param');
}

const emailInboxes = await EmailInbox.findOneById(_id);
if (!emailInboxes) {
const { deletedCount } = await removeEmailInbox(_id);

if (!deletedCount) {
return API.v1.notFound();
}
await EmailInbox.removeById(_id);

return API.v1.success({ _id });
},
},
Expand All @@ -120,7 +132,7 @@ API.v1.addRoute(

// TODO: Chapter day backend - check if user has permission to view this email inbox instead of null values
// TODO: Chapter day: Remove this endpoint and move search to GET /email-inbox
const emailInbox = await EmailInbox.findOne({ email });
const emailInbox = await EmailInbox.findByEmail(email);

return API.v1.success({ emailInbox });
},
Expand All @@ -140,7 +152,7 @@ API.v1.addRoute(
if (!_id) {
throw new Error('error-invalid-param');
}
const emailInbox = await findOneEmailInbox({ _id });
const emailInbox = await EmailInbox.findOneById(_id);

if (!emailInbox) {
return API.v1.notFound();
Expand Down
9 changes: 4 additions & 5 deletions apps/meteor/app/file-upload/server/config/AmazonS3.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import http from 'http';
import https from 'https';
import URL from 'url';

import _ from 'underscore';

import { settings } from '../../../settings/server';
import type { S3Options } from '../../ufs/AmazonS3/server';
import { FileUploadClass, FileUpload } from '../lib/FileUpload';
import '../../ufs/AmazonS3/server';
import { forceDownload } from './helper';

const get: FileUploadClass['get'] = async function (this: FileUploadClass, file, req, res) {
const { query } = URL.parse(req.url || '', true);
const forceDownload = typeof query.download !== 'undefined';
const forcedDownload = forceDownload(req);

const fileUrl = await this.store.getRedirectURL(file, forceDownload);
const fileUrl = await this.store.getRedirectURL(file, forcedDownload);
if (!fileUrl || !file.store) {
res.end();
return;
Expand All @@ -23,7 +22,7 @@ const get: FileUploadClass['get'] = async function (this: FileUploadClass, file,
if (settings.get(`FileUpload_S3_Proxy_${storeType}`)) {
const request = /^https:/.test(fileUrl) ? https : http;

FileUpload.proxyFile(file.name || '', fileUrl, forceDownload, request, req, res);
FileUpload.proxyFile(file.name || '', fileUrl, forcedDownload, request, req, res);
return;
}

Expand Down
4 changes: 3 additions & 1 deletion apps/meteor/app/file-upload/server/config/FileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { UploadFS } from '../../../../server/ufs';
import { settings } from '../../../settings/server';
import { FileUploadClass, FileUpload } from '../lib/FileUpload';
import { getFileRange, setRangeHeaders } from '../lib/ranges';
import { getContentDisposition } from './helper';

const FileSystemUploads = new FileUploadClass({
name: 'FileSystem:Uploads',
Expand All @@ -26,7 +27,8 @@ const FileSystemUploads = new FileUploadClass({
}

file = FileUpload.addExtensionTo(file);
res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(file.name || '')}`);

res.setHeader('Content-Disposition', `${getContentDisposition(req)}; filename*=UTF-8''${encodeURIComponent(file.name || '')}`);
file.uploadedAt && res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
res.setHeader('Content-Type', file.type || 'application/octet-stream');

Expand Down
9 changes: 4 additions & 5 deletions apps/meteor/app/file-upload/server/config/GoogleStorage.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import http from 'http';
import https from 'https';
import URL from 'url';

import _ from 'underscore';

import { settings } from '../../../settings/server';
import { FileUploadClass, FileUpload } from '../lib/FileUpload';
import '../../ufs/GoogleStorage/server';
import { forceDownload } from './helper';

const get: FileUploadClass['get'] = async function (this: FileUploadClass, file, req, res) {
const { query } = URL.parse(req.url || '', true);
const forceDownload = typeof query.download !== 'undefined';
const forcedDownload = forceDownload(req);

const fileUrl = await this.store.getRedirectURL(file, forceDownload);
const fileUrl = await this.store.getRedirectURL(file, forcedDownload);
if (!fileUrl || !file.store) {
res.end();
return;
Expand All @@ -22,7 +21,7 @@ const get: FileUploadClass['get'] = async function (this: FileUploadClass, file,
if (settings.get(`FileUpload_GoogleStorage_Proxy_${storeType}`)) {
const request = /^https:/.test(fileUrl) ? https : http;

FileUpload.proxyFile(file.name || '', fileUrl, forceDownload, request, req, res);
FileUpload.proxyFile(file.name || '', fileUrl, forcedDownload, request, req, res);
return;
}

Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/app/file-upload/server/config/GridFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Logger } from '@rocket.chat/logger';
import { UploadFS } from '../../../../server/ufs';
import { FileUploadClass, FileUpload } from '../lib/FileUpload';
import { getFileRange, setRangeHeaders } from '../lib/ranges';
import { getContentDisposition } from './helper';

const logger = new Logger('FileUpload');

Expand Down Expand Up @@ -161,7 +162,7 @@ new FileUploadClass({
async get(file, req, res) {
file = FileUpload.addExtensionTo(file);

res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(file.name || '')}`);
res.setHeader('Content-Disposition', `${getContentDisposition(req)}; filename*=UTF-8''${encodeURIComponent(file.name || '')}`);
file.uploadedAt && res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
res.setHeader('Content-Type', file.type || 'application/octet-stream');
res.setHeader('Content-Length', file.size || 0);
Expand Down
21 changes: 21 additions & 0 deletions apps/meteor/app/file-upload/server/config/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type http from 'http';
import URL from 'url';

export const forceDownload = (req: http.IncomingMessage): boolean => {
const { query } = URL.parse(req.url || '', true);

const forceDownload = typeof query.download !== 'undefined';
if (forceDownload) {
return true;
}

return query.contentDisposition === 'attachment';
};

export const getContentDisposition = (req: http.IncomingMessage): string => {
const { query } = URL.parse(req.url || '', true);
if (query.contentDisposition === 'inline') {
return 'inline';
}
return 'attachment';
};
21 changes: 15 additions & 6 deletions apps/meteor/app/integrations/server/lib/updateHistory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { IIntegrationHistory, OutgoingIntegrationEvent, IIntegration, IMessage, AtLeast } from '@rocket.chat/core-typings';
import { IntegrationHistory } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';

import { omit } from '../../../../lib/utils/omit';
import { notifyOnIntegrationHistoryChangedById, notifyOnIntegrationHistoryChanged } from '../../../lib/server/lib/notifyListener';

export const updateHistory = async ({
historyId,
Expand Down Expand Up @@ -77,7 +77,12 @@ export const updateHistory = async ({
};

if (historyId) {
await IntegrationHistory.updateOne({ _id: historyId }, { $set: history });
// Projecting just integration field to comply with existing listener behaviour
const integrationHistory = await IntegrationHistory.updateById(historyId, history, { projection: { 'integration._id': 1 } });
if (!integrationHistory) {
throw new Error('error-updating-integration-history');
}
void notifyOnIntegrationHistoryChanged(integrationHistory, 'updated', history);
return historyId;
}

Expand All @@ -86,11 +91,15 @@ export const updateHistory = async ({
throw new Error('error-invalid-integration');
}

history._createdAt = new Date();
// TODO: Had to force type cast here because of function's signature
// It would be easier if we separate into create and update functions
const { insertedId } = await IntegrationHistory.create(history as IIntegrationHistory);

const _id = Random.id();
if (!insertedId) {
throw new Error('error-creating-integration-history');
}

await IntegrationHistory.insertOne({ _id, ...history } as IIntegrationHistory);
void notifyOnIntegrationHistoryChangedById(insertedId, 'inserted');

return _id;
return insertedId;
};
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Meteor.methods<ServerMethods>({
});
}

// Don't sending to IntegrationHistory listener since it don't waits for 'removed' events.
await IntegrationHistory.removeByIntegrationId(integrationId);

notifications.streamIntegrationHistory.emit(integrationId, { type: 'removed', id: integrationId });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const deleteOutgoingIntegration = async (integrationId: string, userId: s
}

await Integrations.removeById(integrationId);
// Don't sending to IntegrationHistory listener since it don't waits for 'removed' events.
await IntegrationHistory.removeByIntegrationId(integrationId);
void notifyOnIntegrationChangedById(integrationId, 'removed');
};
Expand Down
Loading

0 comments on commit 770ade3

Please sign in to comment.