Skip to content

Commit

Permalink
Merge branch 'develop' into fix/retentionSettings
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Sep 12, 2024
2 parents 660eff3 + 18b1b99 commit 5de9bff
Show file tree
Hide file tree
Showing 303 changed files with 1,312 additions and 941 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.
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/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.
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
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);
});
});
6 changes: 5 additions & 1 deletion 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 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
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
1 change: 1 addition & 0 deletions apps/meteor/app/livechat/imports/server/rest/appearance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ API.v1.addRoute(
'Livechat_background',
'Livechat_widget_position',
'Livechat_hide_system_messages',
'Omnichannel_allow_visitors_to_close_conversation',
];

const valid = settings.every((setting) => validSettingList.includes(setting._id));
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/app/livechat/server/api/lib/appearance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export async function findAppearance(): Promise<{ appearance: ISetting[] }> {
'Livechat_background',
'Livechat_widget_position',
'Livechat_hide_system_messages',
'Omnichannel_allow_visitors_to_close_conversation',
],
},
};
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/app/livechat/server/api/lib/livechat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export async function settings({ businessUnit = '' }: { businessUnit?: string }
hiddenSystemMessages: initSettings.Livechat_hide_system_messages,
livechatLogo: initSettings.Assets_livechat_widget_logo,
hideWatermark: initSettings.Livechat_hide_watermark || false,
visitorsCanCloseChat: initSettings.Omnichannel_allow_visitors_to_close_conversation,
},
theme: {
title: initSettings.Livechat_title,
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/livechat/server/api/v1/contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ API.v1.addRoute(
{ authRequired: true, permissionsRequired: ['create-livechat-contact'], validateParams: isPOSTOmnichannelContactsProps },
{
async post() {
if (!process.env.TEST_MODE) {
if (process.env.TEST_MODE?.toUpperCase() !== 'TRUE') {
throw new Meteor.Error('error-not-allowed', 'This endpoint is only allowed in test mode');
}
const contactId = await createContact({ ...this.bodyParams, unknown: false });
Expand All @@ -106,7 +106,7 @@ API.v1.addRoute(
{ authRequired: true, permissionsRequired: ['update-livechat-contact'], validateParams: isPOSTUpdateOmnichannelContactsProps },
{
async post() {
if (!process.env.TEST_MODE) {
if (process.env.TEST_MODE?.toUpperCase() !== 'TRUE') {
throw new Meteor.Error('error-not-allowed', 'This endpoint is only allowed in test mode');
}

Expand Down
4 changes: 4 additions & 0 deletions apps/meteor/app/livechat/server/api/v1/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ API.v1.addRoute(
async post() {
const { rid, token } = this.bodyParams;

if (!rcSettings.get('Omnichannel_allow_visitors_to_close_conversation')) {
throw new Error('error-not-allowed-to-close-conversation');
}

const visitor = await findGuest(token);
if (!visitor) {
throw new Error('invalid-token');
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/app/livechat/server/lib/Contacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ type RegisterContactProps = {

type CreateContactParams = {
name: string;
emails: string[];
phones: string[];
emails?: string[];
phones?: string[];
unknown: boolean;
customFields?: Record<string, string | unknown>;
contactManager?: string;
Expand Down
12 changes: 12 additions & 0 deletions apps/meteor/app/livechat/server/lib/LivechatTyped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import * as Mailer from '../../../mailer/server/api';
import { metrics } from '../../../metrics/server';
import { settings } from '../../../settings/server';
import { businessHourManager } from '../business-hour';
import { createContact } from './Contacts';
import { parseAgentCustomFields, updateDepartmentAgents, validateEmail, normalizeTransferredByData } from './Helper';
import { QueueManager } from './QueueManager';
import { RoutingManager } from './RoutingManager';
Expand Down Expand Up @@ -664,6 +665,16 @@ class LivechatClass {
}
}

if (process.env.TEST_MODE?.toUpperCase() === 'TRUE') {
const contactId = await createContact({
name: name ?? (visitorDataToUpdate.username as string),
emails: email ? [email] : [],
phones: phone ? [phone.number] : [],
unknown: true,
});
visitorDataToUpdate.contactId = contactId;
}

const upsertedLivechatVisitor = await LivechatVisitors.updateOneByIdOrToken(visitorDataToUpdate, {
upsert: true,
returnDocument: 'after',
Expand Down Expand Up @@ -1068,6 +1079,7 @@ class LivechatClass {
'Livechat_background',
'Assets_livechat_widget_logo',
'Livechat_hide_watermark',
'Omnichannel_allow_visitors_to_close_conversation',
] as const;

type SettingTypes = (typeof validSettings)[number] | 'Livechat_Show_Connecting';
Expand Down
Loading

0 comments on commit 5de9bff

Please sign in to comment.