Skip to content

Commit

Permalink
Merge branch 'refactor/OAuth-modal-accessibility' of github.com:Rocke…
Browse files Browse the repository at this point in the history
…tChat/Rocket.Chat into refactor/OAuth-modal-accessibility
  • Loading branch information
rique223 committed Oct 21, 2024
2 parents 1ba55c7 + 9c9c1a6 commit 056e6a4
Show file tree
Hide file tree
Showing 216 changed files with 3,392 additions and 1,004 deletions.
9 changes: 5 additions & 4 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": ["@rocket.chat/release-changelog", { "repo": "RocketChat/Rocket.Chat" }],
"commit": false,
"fixed": [
["@rocket.chat/meteor", "@rocket.chat/core-typings", "@rocket.chat/rest-typings"]
],
"fixed": [["@rocket.chat/meteor", "@rocket.chat/core-typings", "@rocket.chat/rest-typings"]],
"linked": [],
"access": "public",
"baseBranch": "develop",
"updateInternalDependencies": "patch",
"ignore": []
"ignore": [],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"onlyUpdatePeerDependentsWhenOutOfRange": true
}
}
2 changes: 1 addition & 1 deletion .changeset/giant-spiders-train.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---

'@rocket.chat/ui-kit': minor
---

Adds `accessory` properties to `CalloutBlock`
7 changes: 7 additions & 0 deletions .changeset/little-gifts-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@rocket.chat/meteor": major
"@rocket.chat/i18n": major
"@rocket.chat/license": major
---

Adds restrictions to air-gapped environments without a license
6 changes: 6 additions & 0 deletions .changeset/perfect-wolves-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/rest-typings': major
'@rocket.chat/meteor': major
---

Changes custom emoji listing endpoint by moving query params from the 'query' attribute to standard query parameters.
4 changes: 2 additions & 2 deletions .changeset/tidy-suns-move.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
"@rocket.chat/meteor": feat
"@rocket.chat/i18n": feat
'@rocket.chat/meteor': minor
'@rocket.chat/i18n': minor
---

Introduces new visual components into marketplace pages to inform an add-on necessity into the workspace.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ data/
registration.yaml

storybook-static
development/tempo-data/
26 changes: 24 additions & 2 deletions apps/meteor/app/api/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Logger } from '@rocket.chat/logger';
import { Users } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
import type { JoinPathPattern, Method } from '@rocket.chat/rest-typings';
import { tracerSpan } from '@rocket.chat/tracing';
import { Accounts } from 'meteor/accounts-base';
import { DDP } from 'meteor/ddp';
import { DDPCommon } from 'meteor/ddp-common';
Expand Down Expand Up @@ -645,8 +646,29 @@ export class APIClass<TBasePath extends string = ''> extends Restivus {
this.queryFields = options.queryFields;
this.parseJsonQuery = api.parseJsonQuery.bind(this as PartialThis);

result =
(await DDP._CurrentInvocation.withValue(invocation as any, async () => originalAction.apply(this))) || API.v1.success();
result = await tracerSpan(
`${this.request.method} ${this.request.url}`,
{
attributes: {
url: this.request.url,
route: this.request.route,
method: this.request.method,
userId: this.userId,
},
},
async (span) => {
if (span) {
this.response.setHeader('X-Trace-Id', span.spanContext().traceId);
}

const result =
(await DDP._CurrentInvocation.withValue(invocation as any, async () => originalAction.apply(this))) || API.v1.success();

span?.setAttribute('status', result.statusCode);

return result;
},
);

log.http({
status: result.statusCode,
Expand Down
15 changes: 2 additions & 13 deletions apps/meteor/app/api/server/helpers/parseJsonQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,12 @@ export async function parseJsonQuery(api: PartialThis): Promise<{
}
}

// TODO: Remove this once we have all routes migrated to the new API params
const hasSupportedRoutes = [
'/api/v1/directory',
'/api/v1/channels.files',
'/api/v1/integrations.list',
'/api/v1/custom-user-status.list',
'/api/v1/custom-sounds.list',
'/api/v1/channels.list',
'/api/v1/channels.online',
].includes(route);

const isUnsafeQueryParamsAllowed = process.env.ALLOW_UNSAFE_QUERY_AND_FIELDS_API_PARAMS?.toUpperCase() === 'TRUE';
const messageGenerator = ({ endpoint, version, parameter }: { endpoint: string; version: string; parameter: string }): string =>
`The usage of the "${parameter}" parameter in endpoint "${endpoint}" breaks the security of the API and can lead to data exposure. It has been deprecated and will be removed in the version ${version}.`;

let fields: Record<string, 0 | 1> | undefined;
if (params.fields && (isUnsafeQueryParamsAllowed || !hasSupportedRoutes)) {
if (params.fields && isUnsafeQueryParamsAllowed) {
try {
apiDeprecationLogger.parameter(route, 'fields', '8.0.0', response, messageGenerator);
fields = JSON.parse(params.fields) as Record<string, 0 | 1>;
Expand Down Expand Up @@ -119,7 +108,7 @@ export async function parseJsonQuery(api: PartialThis): Promise<{
}

let query: Record<string, any> = {};
if (params.query && (isUnsafeQueryParamsAllowed || !hasSupportedRoutes)) {
if (params.query && isUnsafeQueryParamsAllowed) {
apiDeprecationLogger.parameter(route, 'query', '8.0.0', response, messageGenerator);
try {
query = ejson.parse(params.query);
Expand Down
29 changes: 18 additions & 11 deletions apps/meteor/app/api/server/v1/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { deleteMessageValidatingPermission } from '../../../lib/server/functions
import { processWebhookMessage } from '../../../lib/server/functions/processWebhookMessage';
import { executeSendMessage } from '../../../lib/server/methods/sendMessage';
import { executeUpdateMessage } from '../../../lib/server/methods/updateMessage';
import { applyAirGappedRestrictionsValidation } from '../../../license/server/airGappedRestrictionsWrapper';
import { OEmbed } from '../../../oembed/server/server';
import { executeSetReaction } from '../../../reactions/server/setReaction';
import { settings } from '../../../settings/server';
Expand Down Expand Up @@ -160,7 +161,7 @@ API.v1.addRoute(
{ authRequired: true },
{
async post() {
const messageReturn = (await processWebhookMessage(this.bodyParams, this.user))[0];
const messageReturn = (await applyAirGappedRestrictionsValidation(() => processWebhookMessage(this.bodyParams, this.user)))[0];

if (!messageReturn) {
return API.v1.failure('unknown-error');
Expand Down Expand Up @@ -218,7 +219,9 @@ API.v1.addRoute(
throw new Error("Cannot send system messages using 'chat.sendMessage'");
}

const sent = await executeSendMessage(this.userId, this.bodyParams.message as Pick<IMessage, 'rid'>, this.bodyParams.previewUrls);
const sent = await applyAirGappedRestrictionsValidation(() =>
executeSendMessage(this.userId, this.bodyParams.message as Pick<IMessage, 'rid'>, this.bodyParams.previewUrls),
);
const [message] = await normalizeMessagesForUser([sent], this.userId);

return API.v1.success({
Expand Down Expand Up @@ -318,16 +321,20 @@ API.v1.addRoute(
return API.v1.failure('The room id provided does not match where the message is from.');
}

const msgFromBody = this.bodyParams.text;

// Permission checks are already done in the updateMessage method, so no need to duplicate them
await executeUpdateMessage(
this.userId,
{
_id: msg._id,
msg: this.bodyParams.text,
rid: msg.rid,
customFields: this.bodyParams.customFields as Record<string, any> | undefined,
},
this.bodyParams.previewUrls,
await applyAirGappedRestrictionsValidation(() =>
executeUpdateMessage(
this.userId,
{
_id: msg._id,
msg: msgFromBody,
rid: msg.rid,
customFields: this.bodyParams.customFields as Record<string, any> | undefined,
},
this.bodyParams.previewUrls,
),
);

const updatedMessage = await Messages.findOneById(msg._id);
Expand Down
42 changes: 33 additions & 9 deletions apps/meteor/app/api/server/v1/emoji-custom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Media } from '@rocket.chat/core-services';
import { EmojiCustom } from '@rocket.chat/models';
import { isEmojiCustomList } from '@rocket.chat/rest-typings';
import { Meteor } from 'meteor/meteor';

import { SystemLogger } from '../../../../server/lib/logger/system';
Expand All @@ -11,22 +12,41 @@ import { getPaginationItems } from '../helpers/getPaginationItems';
import { findEmojisCustom } from '../lib/emoji-custom';
import { getUploadFormData } from '../lib/getUploadFormData';

function validateDateParam(paramName: string, paramValue: string | undefined): Date | undefined {
if (!paramValue) {
return undefined;
}

const date = new Date(paramValue);
if (isNaN(date.getTime())) {
throw new Meteor.Error('error-roomId-param-invalid', `The "${paramName}" query parameter must be a valid date.`);
}

return date;
}

API.v1.addRoute(
'emoji-custom.list',
{ authRequired: true },
{ authRequired: true, validateParams: isEmojiCustomList },
{
async get() {
const { query } = await this.parseJsonQuery();
const { updatedSince } = this.queryParams;
if (updatedSince) {
const updatedSinceDate = new Date(updatedSince);
if (isNaN(Date.parse(updatedSince))) {
throw new Meteor.Error('error-roomId-param-invalid', 'The "updatedSince" query parameter must be a valid date.');
}
const { updatedSince, _updatedAt, _id } = this.queryParams;

const updatedSinceDate = validateDateParam('updatedSince', updatedSince);
const _updatedAtDate = validateDateParam('_updatedAt', _updatedAt);

if (updatedSinceDate) {
const [update, remove] = await Promise.all([
EmojiCustom.find({ ...query, _updatedAt: { $gt: updatedSinceDate } }).toArray(),
EmojiCustom.find({
...query,
...(_id ? { _id } : {}),
...(_updatedAtDate ? { _updatedAt: { $gt: _updatedAtDate } } : {}),
_updatedAt: { $gt: updatedSinceDate },
}).toArray(),
EmojiCustom.trashFindDeletedAfter(updatedSinceDate).toArray(),
]);

return API.v1.success({
emojis: {
update,
Expand All @@ -37,7 +57,11 @@ API.v1.addRoute(

return API.v1.success({
emojis: {
update: await EmojiCustom.find(query).toArray(),
update: await EmojiCustom.find({
...query,
...(_id ? { _id } : {}),
...(_updatedAtDate ? { _updatedAt: { $gt: _updatedAtDate } } : {}),
}).toArray(),
remove: [],
},
});
Expand Down
31 changes: 17 additions & 14 deletions apps/meteor/app/api/server/v1/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { createDiscussion } from '../../../discussion/server/methods/createDiscu
import { FileUpload } from '../../../file-upload/server';
import { sendFileMessage } from '../../../file-upload/server/methods/sendFileMessage';
import { leaveRoomMethod } from '../../../lib/server/methods/leaveRoom';
import { applyAirGappedRestrictionsValidation } from '../../../license/server/airGappedRestrictionsWrapper';
import { settings } from '../../../settings/server';
import { API } from '../api';
import { composeRoomWithLastMessage } from '../helpers/composeRoomWithLastMessage';
Expand Down Expand Up @@ -199,7 +200,9 @@ API.v1.addRoute(

delete fields.description;

await sendFileMessage(this.userId, { roomId: this.urlParams.rid, file: uploadedFile, msgData: fields });
await applyAirGappedRestrictionsValidation(() =>
sendFileMessage(this.userId, { roomId: this.urlParams.rid, file: uploadedFile, msgData: fields }),
);

const message = await Messages.getMessageByFileIdAndUsername(uploadedFile._id, this.userId);

Expand Down Expand Up @@ -299,10 +302,8 @@ API.v1.addRoute(
file.description = this.bodyParams.description;
delete this.bodyParams.description;

await sendFileMessage(
this.userId,
{ roomId: this.urlParams.rid, file, msgData: this.bodyParams },
{ parseAttachmentsForE2EE: false },
await applyAirGappedRestrictionsValidation(() =>
sendFileMessage(this.userId, { roomId: this.urlParams.rid, file, msgData: this.bodyParams }, { parseAttachmentsForE2EE: false }),
);

await Uploads.confirmTemporaryFile(this.urlParams.fileId, this.userId);
Expand Down Expand Up @@ -479,15 +480,17 @@ API.v1.addRoute(
return API.v1.failure('Body parameter "encrypted" must be a boolean when included.');
}

const discussion = await createDiscussion(this.userId, {
prid,
pmid,
t_name,
reply,
users: users?.filter(isTruthy) || [],
encrypted,
topic,
});
const discussion = await applyAirGappedRestrictionsValidation(() =>
createDiscussion(this.userId, {
prid,
pmid,
t_name,
reply,
users: users?.filter(isTruthy) || [],
encrypted,
topic,
}),
);

return API.v1.success({ discussion });
},
Expand Down
4 changes: 1 addition & 3 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,6 @@ API.v1.addRoute(
{ authRequired: true, validateParams: isUsersInfoParamsGetProps },
{
async get() {
const { fields } = await this.parseJsonQuery();

const searchTerms: [string, 'id' | 'username' | 'importId'] | false =
('userId' in this.queryParams && !!this.queryParams.userId && [this.queryParams.userId, 'id']) ||
('username' in this.queryParams && !!this.queryParams.username && [this.queryParams.username, 'username']) ||
Expand All @@ -426,7 +424,7 @@ API.v1.addRoute(
return API.v1.failure('User not found.');
}
const myself = user._id === this.userId;
if (fields.userRooms === 1 && (myself || (await hasPermissionAsync(this.userId, 'view-other-user-channels')))) {
if (this.queryParams.includeUserRooms === 'true' && (myself || (await hasPermissionAsync(this.userId, 'view-other-user-channels')))) {
return API.v1.success({
user: {
...user,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,6 @@ import { settings } from '../../../settings/client';
import { sdk } from '../../../utils/client/lib/SDKClient';
import { CannedResponse } from '../collections/CannedResponse';

const events = {
changed: ({ type, ...response }) => {
CannedResponse.upsert({ _id: response._id }, response);
},
removed: (response) => CannedResponse.remove({ _id: response._id }),
};

Meteor.startup(() => {
Tracker.autorun(async (c) => {
if (!Meteor.userId()) {
Expand All @@ -27,12 +20,24 @@ Meteor.startup(() => {
Tracker.afterFlush(() => {
try {
// TODO: check options
sdk.stream('canned-responses', ['canned-responses'], (response, options) => {
sdk.stream('canned-responses', ['canned-responses'], (...[response, options]) => {
const { agentsId } = options || {};
if (Array.isArray(agentsId) && !agentsId.includes(Meteor.userId())) {
return;
}
events[response.type](response);

switch (response.type) {
case 'changed': {
const { type, ...fields } = response;
CannedResponse.upsert({ _id: response._id }, fields);
break;
}

case 'removed': {
CannedResponse.remove({ _id: response._id });
break;
}
}
});
} catch (error) {
console.log(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import { Accounts } from 'meteor/accounts-base';
import { e2e } from './rocketchat.e2e';

Accounts.onLogout(() => {
e2e.stopClient();
void e2e.stopClient();
});
Loading

0 comments on commit 056e6a4

Please sign in to comment.