Skip to content

Commit

Permalink
Merge branch 'develop' into refactor/required-field-copy
Browse files Browse the repository at this point in the history
  • Loading branch information
rique223 committed Sep 13, 2024
2 parents 38b2824 + 98b6a20 commit f60a840
Show file tree
Hide file tree
Showing 783 changed files with 3,240 additions and 2,308 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-cherries-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Allow to use the token from `room.v` when requesting transcript instead of visitor token. Visitors may change their tokens at any time, rendering old conversations impossible to access for them (or for APIs depending on token) as the visitor token won't match the `room.v` token.
8 changes: 8 additions & 0 deletions .changeset/healthy-rivers-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@rocket.chat/meteor": minor
"@rocket.chat/i18n": minor
"@rocket.chat/livechat": minor
---

Added new setting `Allow visitors to finish conversations` that allows admins to decide if omnichannel visitors can close a conversation or not. This doesn't affect agent's capabilities of room closing, neither apps using the livechat bridge to close rooms.
However, if currently your integration relies on `livechat/room.close` endpoint for closing conversations, it's advised to use the authenticated version `livechat/room.closeByUser` of it before turning off this setting.
5 changes: 5 additions & 0 deletions .changeset/khaki-cameras-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes an issue where the retention policy warning keep displaying even if the retention is disabled inside the room
13 changes: 13 additions & 0 deletions .changeset/many-balloons-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@rocket.chat/uikit-playground': minor
'@rocket.chat/fuselage-ui-kit': minor
'@rocket.chat/ui-theming': minor
'@rocket.chat/ui-video-conf': minor
'@rocket.chat/ui-composer': minor
'@rocket.chat/gazzodown': minor
'@rocket.chat/ui-avatar': minor
'@rocket.chat/ui-client': minor
'@rocket.chat/meteor': minor
---

Replaced new `SidebarV2` components under feature preview
5 changes: 5 additions & 0 deletions .changeset/many-rules-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates)
5 changes: 5 additions & 0 deletions .changeset/nasty-tools-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed a code issue on NPS service. It was passing `startAt` as the expiration date when creating a banner.
5 changes: 5 additions & 0 deletions .changeset/pink-swans-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fixed retention policy max age settings not being respected after upgrade
6 changes: 6 additions & 0 deletions .changeset/short-drinks-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/message-parser': patch
'@rocket.chat/peggy-loader': patch
---

Improved the performance of the message parser
6 changes: 6 additions & 0 deletions .changeset/tiny-geckos-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---

Added a new setting which allows workspace admins to disable email two factor authentication for SSO (OAuth) users. If enabled, SSO users won't be asked for email two factor authentication.
5 changes: 5 additions & 0 deletions .changeset/wet-hats-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed issue that caused an infinite loading state when uploading a private app to Rocket.Chat
41 changes: 41 additions & 0 deletions .github/workflows/ci-deploy-gh-pages-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# .github/workflows/ci-preview.yml
name: Deploy PR previews
concurrency: preview-${{ github.ref }}
on:
pull_request:
types:
- opened
- reopened
- synchronize
- closed

jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: rharkor/[email protected]
if: github.event.action != 'closed'

- name: Setup NodeJS
uses: ./.github/actions/setup-node
if: github.event.action != 'closed'
with:
node-version: 14.21.3
cache-modules: true
install: true

- name: Build
if: github.event.action != 'closed'
run: |
yarn turbo run build-preview
yarn turbo run .:build-preview-move
npx indexifier .preview --html --extensions .html > .preview/index.html
- uses: rossjrw/pr-preview-action@v1
with:
source-dir: .preview
preview-branch: gh-pages
umbrella-dir: pr-preview
action: auto
38 changes: 38 additions & 0 deletions .github/workflows/ci-deploy-gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# .github/workflows/ci-preview-deploy.yml
name: Deploy GitHub Pages
concurrency: preview-deploy-${{ github.ref }}
on:
push:
branches:
- main
- master
- develop
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: rharkor/[email protected]

- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: 14.21.3
cache-modules: true
install: true

- name: Build
run: |
yarn turbo run build-preview
yarn turbo run .:build-preview-move
npx indexifier .preview --html --extensions .html > .preview/index.html
mv .preview ${{ github.ref_name }}
mkdir .preview
mv ${{ github.ref_name }} .preview
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: .preview
keep_files: true
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ yarn-error.log*
.history
.envrc

.preview

*.sublime-workspace

**/.vim/
Expand Down
99 changes: 99 additions & 0 deletions .yarn/patches/react-i18next-npm-15.0.1-0812bb73aa.patch

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions _templates/package/new/package.json.ejs.t
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ to: packages/<%= name %>/package.json
"test": "jest",
"build": "rm -rf dist && tsc -p tsconfig.json",
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput"
"build-preview": "mkdir -p ../../.preview && cp -r ./dist ../../.preview/<%= name.toLowerCase() %>"
},
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
Expand Down
70 changes: 70 additions & 0 deletions apps/meteor/app/2fa/server/code/EmailCheck.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { expect } from 'chai';
import { describe, it } from 'mocha';
import proxyquire from 'proxyquire';
import sinon from 'sinon';

const settingsMock = sinon.stub();

const { EmailCheck } = proxyquire.noCallThru().load('./EmailCheck', {
'@rocket.chat/models': {
Users: {},
},
'meteor/accounts-base': {
Accounts: {
_bcryptRounds: () => '123',
},
},
'../../../../server/lib/i18n': {
i18n: {
t: (key: string) => key,
},
},
'../../../mailer/server/api': {
send: () => undefined,
},
'../../../settings/server': {
settings: {
get: settingsMock,
},
},
});

const normalUserMock = { services: { email2fa: { enabled: true } }, emails: [{ email: '[email protected]', verified: true }] };
const normalUserWithUnverifiedEmailMock = {
services: { email2fa: { enabled: true } },
emails: [{ email: '[email protected]', verified: false }],
};
const OAuthUserMock = { services: { google: {} }, emails: [{ email: '[email protected]', verified: true }] };

describe('EmailCheck', () => {
let emailCheck: typeof EmailCheck;
beforeEach(() => {
settingsMock.reset();

emailCheck = new EmailCheck();
});

it('should return EmailCheck is enabled for a normal user', () => {
settingsMock.returns(true);

const isEmail2FAEnabled = emailCheck.isEnabled(normalUserMock);

expect(isEmail2FAEnabled).to.be.equal(true);
});

it('should return EmailCheck is not enabled for a normal user with unverified email', () => {
settingsMock.returns(true);

const isEmail2FAEnabled = emailCheck.isEnabled(normalUserWithUnverifiedEmailMock);

expect(isEmail2FAEnabled).to.be.equal(false);
});

it('should return EmailCheck is not enabled for a OAuth user with setting being false', () => {
settingsMock.returns(true);

const isEmail2FAEnabled = emailCheck.isEnabled(OAuthUserMock);

expect(isEmail2FAEnabled).to.be.equal(false);
});
});
8 changes: 6 additions & 2 deletions apps/meteor/app/2fa/server/code/EmailCheck.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { IUser } from '@rocket.chat/core-typings';
import { isOAuthUser, type IUser } from '@rocket.chat/core-typings';
import { Users } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
import bcrypt from 'bcrypt';
Expand All @@ -24,6 +24,10 @@ export class EmailCheck implements ICodeCheck {
return false;
}

if (!settings.get('Accounts_twoFactorAuthentication_email_available_for_OAuth_users') && isOAuthUser(user)) {
return false;
}

if (!user.services?.email2fa?.enabled) {
return false;
}
Expand All @@ -34,7 +38,7 @@ export class EmailCheck implements ICodeCheck {
private async send2FAEmail(address: string, random: string, user: IUser): Promise<void> {
const language = user.language || settings.get('Language') || 'en';

const t = (s: string): string => i18n.t(s, { lng: language });
const t = i18n.getFixedT(language);

await Mailer.send({
to: address,
Expand Down
12 changes: 4 additions & 8 deletions apps/meteor/app/2fa/server/code/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,10 @@ function getAvailableMethodNames(user: IUser): string[] {
export async function getUserForCheck(userId: string): Promise<IUser | null> {
return Users.findOneById(userId, {
projection: {
'emails': 1,
'language': 1,
'createdAt': 1,
'services.totp': 1,
'services.email2fa': 1,
'services.emailCode': 1,
'services.password': 1,
'services.resume.loginTokens': 1,
emails: 1,
language: 1,
createdAt: 1,
services: 1,
},
});
}
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/2fa/server/functions/resetTOTP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const sendResetNotification = async function (uid: string): Promise<void> {
return;
}

const t = (s: string): string => i18n.t(s, { lng: language });
const t = i18n.getFixedT(language);
const text = `
${t('Your_TOTP_has_been_reset')}
Expand Down
14 changes: 9 additions & 5 deletions apps/meteor/app/api/server/v1/misc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import crypto from 'crypto';

import type { IUser } from '@rocket.chat/core-typings';
import { isOAuthUser, type IUser } from '@rocket.chat/core-typings';
import { Settings, Users } from '@rocket.chat/models';
import {
isShieldSvgProps,
Expand All @@ -26,7 +26,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP
import { passwordPolicy } from '../../../lib/server';
import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener';
import { settings } from '../../../settings/server';
import { getDefaultUserFields } from '../../../utils/server/functions/getDefaultUserFields';
import { getBaseUserFields } from '../../../utils/server/functions/getBaseUserFields';
import { isSMTPConfigured } from '../../../utils/server/functions/isSMTPConfigured';
import { getURL } from '../../../utils/server/getURL';
import { API } from '../api';
Expand Down Expand Up @@ -176,15 +176,19 @@ API.v1.addRoute(
{ authRequired: true },
{
async get() {
const fields = getDefaultUserFields();
const { services, ...user } = (await Users.findOneById(this.userId, { projection: fields })) as IUser;
const userFields = { ...getBaseUserFields(), services: 1 };
const { services, ...user } = (await Users.findOneById(this.userId, { projection: userFields })) as IUser;

return API.v1.success(
await getUserInfo({
...user,
isOAuthUser: isOAuthUser({ ...user, services }),
...(services && {
services: {
...services,
...(services.github && { github: services.github }),
...(services.gitlab && { gitlab: services.gitlab }),
...(services.email2fa?.enabled && { email2fa: { enabled: services.email2fa.enabled } }),
...(services.totp?.enabled && { totp: { enabled: services.totp.enabled } }),
password: {
// The password hash shouldn't be leaked but the client may need to know if it exists.
exists: Boolean(services?.password?.bcrypt),
Expand Down
28 changes: 21 additions & 7 deletions apps/meteor/app/authorization/server/functions/canDeleteMessage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { IUser } from '@rocket.chat/core-typings';
import type { IUser, IRoom } from '@rocket.chat/core-typings';
import { Rooms } from '@rocket.chat/models';

import { getValue } from '../../../settings/server/raw';
import { canAccessRoomAsync } from './canAccessRoom';
import { hasPermissionAsync } from './hasPermission';

const elapsedTime = (ts: Date): number => {
Expand All @@ -13,6 +14,25 @@ export const canDeleteMessageAsync = async (
uid: string,
{ u, rid, ts }: { u: Pick<IUser, '_id' | 'username'>; rid: string; ts: Date },
): Promise<boolean> => {
const room = await Rooms.findOneById<Pick<IRoom, '_id' | 'ro' | 'unmuted' | 't' | 'teamId' | 'prid'>>(rid, {
projection: {
_id: 1,
ro: 1,
unmuted: 1,
t: 1,
teamId: 1,
prid: 1,
},
});

if (!room) {
return false;
}

if (!(await canAccessRoomAsync(room, { _id: uid }))) {
return false;
}

const forceDelete = await hasPermissionAsync(uid, 'force-delete-message', rid);

if (forceDelete) {
Expand Down Expand Up @@ -45,12 +65,6 @@ export const canDeleteMessageAsync = async (
}
}

const room = await Rooms.findOneById(rid, { projection: { ro: 1, unmuted: 1 } });

if (!room) {
return false;
}

if (room.ro === true && !(await hasPermissionAsync(uid, 'post-readonly', rid))) {
// Unless the user was manually unmuted
if (u.username && !(room.unmuted || []).includes(u.username)) {
Expand Down
Loading

0 comments on commit f60a840

Please sign in to comment.