Skip to content

Commit

Permalink
Merge branch 'develop' into fix/use-all-initials
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriellsh authored Dec 17, 2024
2 parents 65b158e + e1bb39d commit 5ebde0a
Show file tree
Hide file tree
Showing 26 changed files with 238 additions and 112 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-nails-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/apps-engine': patch
---

Adds simple app subprocess metrics report
5 changes: 5 additions & 0 deletions .changeset/honest-kings-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/apps-engine': patch
---

Attempts to restart an app subprocess if the spawn command fails
5 changes: 5 additions & 0 deletions .changeset/quiet-radios-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/apps-engine': patch
---

Fixes an issue while collecting the error message from a failed restart attempt of an app subprocess
5 changes: 5 additions & 0 deletions .changeset/young-dots-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/apps-engine': patch
---

Prevents app:getStatus requests from timing out in some cases
6 changes: 4 additions & 2 deletions apps/meteor/app/lib/server/functions/addUserToRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ export const addUserToRoom = async function (
{
skipSystemMessage,
skipAlertSound,
createAsHidden = false,
}: {
skipSystemMessage?: boolean;
skipAlertSound?: boolean;
createAsHidden?: boolean;
} = {},
): Promise<boolean | undefined> {
const now = new Date();
Expand Down Expand Up @@ -84,8 +86,8 @@ export const addUserToRoom = async function (

const { insertedId } = await Subscriptions.createWithRoomAndUser(room, userToBeAdded as IUser, {
ts: now,
open: true,
alert: !skipAlertSound,
open: !createAsHidden,
alert: createAsHidden ? false : !skipAlertSound,
unread: 1,
userMentions: 1,
groupMentions: 0,
Expand Down
4 changes: 1 addition & 3 deletions apps/meteor/app/lib/server/functions/createRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ async function createUsersSubscriptions({

memberIds.push(member._id);

const extra: Partial<ISubscriptionExtraData> = options?.subscriptionExtra || {};

extra.open = true;
const extra: Partial<ISubscriptionExtraData> = { open: true, ...options?.subscriptionExtra };

if (room.prid) {
extra.prid = room.prid;
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/livechat/server/lib/Helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const createLivechatRoom = async (
const source = extraRoomInfo.source || roomInfo.source;

if (settings.get<string>('Livechat_Require_Contact_Verification') === 'always') {
await LivechatContacts.updateContactChannel({ visitorId: _id, source }, { verified: false });
await LivechatContacts.setChannelVerifiedStatus({ visitorId: _id, source }, false);
}

const contactId = await migrateVisitorIfMissingContact(_id, source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Livechat } from '../../../../../../app/livechat/server/lib/LivechatType
import { i18n } from '../../../../../../server/lib/i18n';

export async function changeContactBlockStatus({ block, visitor }: { visitor: ILivechatContactVisitorAssociation; block: boolean }) {
const result = await LivechatContacts.updateContactChannel(visitor, { blocked: block });
const result = await LivechatContacts.setChannelBlockStatus(visitor, block);

if (!result.modifiedCount) {
throw new Error('error-contact-not-found');
Expand Down
18 changes: 4 additions & 14 deletions apps/meteor/ee/server/patches/verifyContactChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,10 @@ async function _verifyContactChannel(
session.startTransaction();
logger.debug({ msg: 'Start verifying contact channel', contactId, visitorId, roomId });

await LivechatContacts.updateContactChannel(
{
visitorId,
source: room.source,
},
{
verified: true,
verifiedAt: new Date(),
field,
value: value.toLowerCase(),
},
{},
{ session },
);
const updater = LivechatContacts.getUpdater();
LivechatContacts.setVerifiedUpdateQuery(true, updater);
LivechatContacts.setFieldAndValueUpdateQuery(field, value.toLowerCase(), updater);
await LivechatContacts.updateFromUpdaterByAssociation({ visitorId, source: room.source }, updater, { session });

await LivechatRooms.update({ _id: roomId }, { $set: { verified: true } }, { session });
logger.debug({ msg: 'Merging contacts', contactId, visitorId, roomId });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import sinon from 'sinon';

const modelsMock = {
LivechatContacts: {
updateContactChannel: sinon.stub(),
getUpdater: sinon.stub(),
setVerifiedUpdateQuery: sinon.stub(),
setFieldAndValueUpdateQuery: sinon.stub(),
updateFromUpdaterByAssociation: sinon.stub(),
},
LivechatRooms: {
update: sinon.stub(),
Expand Down Expand Up @@ -44,7 +47,10 @@ const { runVerifyContactChannel } = proxyquire.noCallThru().load('../../../../..

describe('verifyContactChannel', () => {
beforeEach(() => {
modelsMock.LivechatContacts.updateContactChannel.reset();
modelsMock.LivechatContacts.getUpdater.reset();
modelsMock.LivechatContacts.setVerifiedUpdateQuery.reset();
modelsMock.LivechatContacts.setFieldAndValueUpdateQuery.reset();
modelsMock.LivechatContacts.updateFromUpdaterByAssociation.reset();
modelsMock.LivechatRooms.update.reset();
modelsMock.LivechatInquiry.findOneByRoomId.reset();
modelsMock.LivechatRooms.findOneById.reset();
Expand All @@ -55,6 +61,8 @@ describe('verifyContactChannel', () => {
mergeContactsStub.reset();
queueManager.processNewInquiry.reset();
queueManager.verifyInquiry.reset();

modelsMock.LivechatContacts.getUpdater.returns({});
});

afterEach(() => {
Expand All @@ -68,24 +76,23 @@ describe('verifyContactChannel', () => {
await runVerifyContactChannel(() => undefined, {
contactId: 'contactId',
field: 'field',
value: 'value',
value: 'Value',
visitorId: 'visitorId',
roomId: 'roomId',
});

expect(modelsMock.LivechatContacts.getUpdater.calledOnce).to.be.true;
expect(modelsMock.LivechatContacts.setVerifiedUpdateQuery.calledOnceWith(true, {})).to.be.true;
expect(modelsMock.LivechatContacts.setFieldAndValueUpdateQuery.calledOnceWith('field', 'value', {})).to.be.true;
expect(
modelsMock.LivechatContacts.updateContactChannel.calledOnceWith(
modelsMock.LivechatContacts.updateFromUpdaterByAssociation.calledOnceWith(
sinon.match({
visitorId: 'visitorId',
source: sinon.match({
type: 'sms',
}),
}),
sinon.match({
verified: true,
field: 'field',
value: 'value',
}),
{},
),
).to.be.true;
expect(modelsMock.LivechatRooms.update.calledOnceWith({ _id: 'roomId' }, { $set: { verified: true } })).to.be.true;
Expand Down Expand Up @@ -116,21 +123,21 @@ describe('verifyContactChannel', () => {
roomId: 'roomId',
});

expect(modelsMock.LivechatContacts.getUpdater.calledOnce).to.be.true;
expect(modelsMock.LivechatContacts.setVerifiedUpdateQuery.calledOnceWith(true, {})).to.be.true;
expect(modelsMock.LivechatContacts.setFieldAndValueUpdateQuery.calledOnceWith('field', 'value', {})).to.be.true;
expect(
modelsMock.LivechatContacts.updateContactChannel.calledOnceWith(
modelsMock.LivechatContacts.updateFromUpdaterByAssociation.calledOnceWith(
sinon.match({
visitorId: 'visitorId',
source: sinon.match({
type: 'sms',
}),
}),
sinon.match({
verified: true,
field: 'field',
value: 'value',
}),
{},
),
).to.be.true;

expect(modelsMock.LivechatRooms.update.calledOnceWith({ _id: 'roomId' }, { $set: { verified: true } })).to.be.true;
expect(
mergeContactsStub.calledOnceWith(
Expand Down Expand Up @@ -160,7 +167,11 @@ describe('verifyContactChannel', () => {
}),
).to.be.rejectedWith('error-invalid-room');

expect(modelsMock.LivechatContacts.updateContactChannel.notCalled).to.be.true;
expect(modelsMock.LivechatContacts.getUpdater.notCalled).to.be.true;
expect(modelsMock.LivechatContacts.setVerifiedUpdateQuery.notCalled).to.be.true;
expect(modelsMock.LivechatContacts.setFieldAndValueUpdateQuery.notCalled).to.be.true;
expect(modelsMock.LivechatContacts.updateFromUpdaterByAssociation.notCalled).to.be.true;

expect(modelsMock.LivechatRooms.update.notCalled).to.be.true;
expect(mergeContactsStub.notCalled).to.be.true;
expect(queueManager.verifyInquiry.notCalled).to.be.true;
Expand All @@ -180,21 +191,21 @@ describe('verifyContactChannel', () => {
}),
).to.be.rejectedWith('error-invalid-inquiry');

expect(modelsMock.LivechatContacts.getUpdater.calledOnce).to.be.true;
expect(modelsMock.LivechatContacts.setVerifiedUpdateQuery.calledOnceWith(true, {})).to.be.true;
expect(modelsMock.LivechatContacts.setFieldAndValueUpdateQuery.calledOnceWith('field', 'value', {})).to.be.true;
expect(
modelsMock.LivechatContacts.updateContactChannel.calledOnceWith(
modelsMock.LivechatContacts.updateFromUpdaterByAssociation.calledOnceWith(
sinon.match({
visitorId: 'visitorId',
source: sinon.match({
type: 'sms',
}),
}),
sinon.match({
verified: true,
field: 'field',
value: 'value',
}),
{},
),
).to.be.true;

expect(modelsMock.LivechatRooms.update.calledOnceWith({ _id: 'roomId' }, { $set: { verified: true } })).to.be.true;
expect(
mergeContactsStub.calledOnceWith(
Expand Down
6 changes: 5 additions & 1 deletion apps/meteor/server/models/raw/Avatars.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { IAvatar, RocketChatRecordDeleted, IUser } from '@rocket.chat/core-typings';
import type { IAvatarsModel } from '@rocket.chat/model-typings';
import type { Collection, Db, FindOptions } from 'mongodb';
import type { Collection, Db, IndexDescription, FindOptions } from 'mongodb';

import { BaseUploadModelRaw } from './BaseUploadModel';

Expand All @@ -9,6 +9,10 @@ export class AvatarsRaw extends BaseUploadModelRaw implements IAvatarsModel {
super(db, 'avatars', trash);
}

protected modelIndexes(): IndexDescription[] {
return [...super.modelIndexes(), { key: { userId: 1 }, sparse: true }];
}

findOneByUserId(userId: IUser['_id'], options?: FindOptions<IAvatar>) {
return this.findOne({ userId }, options);
}
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/server/models/raw/BaseRaw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ export abstract class BaseRaw<
return new UpdaterImpl<T>();
}

public updateFromUpdater(query: Filter<T>, updater: Updater<T>): Promise<UpdateResult> {
public updateFromUpdater(query: Filter<T>, updater: Updater<T>, options: UpdateOptions = {}): Promise<UpdateResult> {
const updateFilter = updater.getUpdateFilter();
return this.updateOne(query, updateFilter).catch((e) => {
return this.updateOne(query, updateFilter, options).catch((e) => {
console.warn(e, updateFilter);
return Promise.reject(e);
});
Expand Down
1 change: 0 additions & 1 deletion apps/meteor/server/models/raw/BaseUploadModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ type T = IUpload;
export abstract class BaseUploadModelRaw extends BaseRaw<T> implements IBaseUploadsModel<T> {
protected modelIndexes(): IndexDescription[] {
return [
{ key: { userId: 1 }, sparse: true },
{ key: { name: 1 }, sparse: true },
{ key: { rid: 1 }, sparse: true },
{ key: { expiresAt: 1 }, sparse: true },
Expand Down
45 changes: 29 additions & 16 deletions apps/meteor/server/models/raw/LivechatContacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
ILivechatVisitor,
RocketChatRecordDeleted,
} from '@rocket.chat/core-typings';
import type { FindPaginated, ILivechatContactsModel, InsertionModel } from '@rocket.chat/model-typings';
import type { FindPaginated, ILivechatContactsModel, InsertionModel, Updater } from '@rocket.chat/model-typings';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import type {
Document,
Expand Down Expand Up @@ -198,24 +198,37 @@ export class LivechatContactsRaw extends BaseRaw<ILivechatContact> implements IL
return Boolean(await this.findOne(this.makeQueryForVisitor(visitor, { blocked: true }), { projection: { _id: 1 } }));
}

async updateContactChannel(
setChannelBlockStatus(visitor: ILivechatContactVisitorAssociation, blocked: boolean): Promise<UpdateResult> {
return this.updateOne(this.makeQueryForVisitor(visitor), { $set: { 'channels.$.blocked': blocked } });
}

setChannelVerifiedStatus(visitor: ILivechatContactVisitorAssociation, verified: boolean): Promise<UpdateResult> {
return this.updateOne(this.makeQueryForVisitor(visitor), {
$set: {
'channels.$.verified': verified,
...(verified && { 'channels.$.verifiedAt': new Date() }),
},
});
}

setVerifiedUpdateQuery(verified: boolean, contactUpdater: Updater<ILivechatContact>): Updater<ILivechatContact> {
if (verified) {
contactUpdater.set('channels.$.verifiedAt', new Date());
}
return contactUpdater.set('channels.$.verified', verified);
}

setFieldAndValueUpdateQuery(field: string, value: string, contactUpdater: Updater<ILivechatContact>): Updater<ILivechatContact> {
contactUpdater.set('channels.$.field', field);
return contactUpdater.set('channels.$.value', value);
}

updateFromUpdaterByAssociation(
visitor: ILivechatContactVisitorAssociation,
data: Partial<ILivechatContactChannel>,
contactData?: Partial<Omit<ILivechatContact, 'channels'>>,
contactUpdater: Updater<ILivechatContact>,
options: UpdateOptions = {},
): Promise<UpdateResult> {
return this.updateOne(
this.makeQueryForVisitor(visitor),
{
$set: {
...contactData,
...(Object.fromEntries(
Object.keys(data).map((key) => [`channels.$.${key}`, data[key as keyof ILivechatContactChannel]]),
) as UpdateFilter<ILivechatContact>['$set']),
},
},
options,
);
return this.updateFromUpdater(this.makeQueryForVisitor(visitor), contactUpdater, options);
}

async findSimilarVerifiedContacts(
Expand Down
5 changes: 4 additions & 1 deletion apps/meteor/server/services/video-conference/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,9 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf
},
{
creator: user._id,
subscriptionExtra: {
open: false,
},
},
);

Expand Down Expand Up @@ -1190,7 +1193,7 @@ export class VideoConfService extends ServiceClassInternal implements IVideoConf

private async addUserToDiscussion(rid: IRoom['_id'], uid: IUser['_id']): Promise<void> {
try {
await Room.addUserToRoom(rid, { _id: uid }, undefined, { skipAlertSound: true });
await Room.addUserToRoom(rid, { _id: uid }, undefined, { skipSystemMessage: true, createAsHidden: true });
} catch (error) {
// Ignore any errors here so that the subscription doesn't block the user from participating in the conference.
logger.error({
Expand Down
27 changes: 27 additions & 0 deletions apps/meteor/tests/end-to-end/apps/video-conferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,33 @@ describe('Apps - Video Conferences', () => {
.that.satisfies((msg: string) => msg.includes('Chat History'));
});
});

it('should have created a subscription with open = false', async function () {
if (!process.env.IS_EE) {
this.skip();
return;
}

await request
.get(api('subscriptions.getOne'))
.set(credentials)
.query({
roomId: discussionRid,
})
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('subscription').and.to.be.an('object');
expect(res.body.subscription).to.have.a.property('rid').equal(discussionRid);
expect(res.body.subscription)
.to.have.a.property('fname')
.that.is.a('string')
.that.satisfies((msg: string) => !msg.startsWith('Chat History'))
.that.satisfies((msg: string) => msg.includes('Chat History'));
expect(res.body.subscription).to.have.a.property('open', false);
expect(res.body.subscription).to.have.a.property('alert', false);
});
});
});

describe('[Persistent Chat provider with the persistent chat feature enabled and custom discussion names]', () => {
Expand Down
Loading

0 comments on commit 5ebde0a

Please sign in to comment.