Skip to content

Commit

Permalink
Merge branch 'feat/directory' of github.com:RocketChat/Rocket.Chat in…
Browse files Browse the repository at this point in the history
…to feat/directory

* 'feat/directory' of github.com:RocketChat/Rocket.Chat:
  Show correctly and search by discussions
  Fix: Notifications of Group DM were not showing the room name (#17058)
  Fix: Last message of Group DMs not showing the sender (#17059)
  Regression: Invite links working for group DMs (#17056)
  Regression: Do not refresh statistics when opening the info panel (#17060)
  Regression: Fix removing user not removing his 1-on-1 DMs (#17057)
  • Loading branch information
ggazzo committed Mar 29, 2020
2 parents 7ae1fc4 + 5fba758 commit 55227d3
Show file tree
Hide file tree
Showing 16 changed files with 98 additions and 36 deletions.
8 changes: 7 additions & 1 deletion app/invites/server/functions/findOrCreateInvite.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Random } from 'meteor/random';

import { hasPermission } from '../../../authorization';
import { Notifications } from '../../../notifications';
import { Invites, Subscriptions } from '../../../models';
import { Invites, Subscriptions, Rooms } from '../../../models/server';
import { settings } from '../../../settings';
import { getURL } from '../../../utils/lib/getURL';
import { roomTypes, RoomMemberActions } from '../../../utils/server';

function getInviteUrl(invite) {
const { _id } = invite;
Expand Down Expand Up @@ -40,6 +41,11 @@ export const findOrCreateInvite = (userId, invite) => {
throw new Meteor.Error('error-invalid-room', 'The rid field is invalid', { method: 'findOrCreateInvite', field: 'rid' });
}

const room = Rooms.findOneById(invite.rid);
if (!roomTypes.getConfig(room.t).allowMemberAction(room, RoomMemberActions.INVITE)) {
throw new Meteor.Error('error-room-type-not-allowed', 'Cannot create invite links for this room type', { method: 'findOrCreateInvite' });
}

let { days, maxUses } = invite;

if (!possibleDays.includes(days)) {
Expand Down
5 changes: 5 additions & 0 deletions app/invites/server/functions/useInviteToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Meteor } from 'meteor/meteor';
import { Invites, Users, Subscriptions } from '../../../models/server';
import { validateInviteToken } from './validateInviteToken';
import { addUserToRoom } from '../../../lib/server/functions/addUserToRoom';
import { roomTypes, RoomMemberActions } from '../../../utils/server';

export const useInviteToken = (userId, token) => {
if (!userId) {
Expand All @@ -15,6 +16,10 @@ export const useInviteToken = (userId, token) => {

const { inviteData, room } = validateInviteToken(token);

if (!roomTypes.getConfig(room.t).allowMemberAction(room, RoomMemberActions.INVITE)) {
throw new Meteor.Error('error-room-type-not-allowed', 'Can\'t join room of this type via invite', { method: 'useInviteToken', field: 'token' });
}

const user = Users.findOneById(userId);
Users.updateInviteToken(user._id, token);

Expand Down
13 changes: 10 additions & 3 deletions app/lib/lib/roomTypes/direct.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,17 @@ export class DirectMessageRoomType extends RoomTypeConfig {
return {};
}

const title = settings.get('UI_Use_Real_Name') ? user.name : `@${ user.username }`;
const text = notificationMessage;
if (this.isGroupChat(room)) {
return {
title: this.roomName(room),
text: `${ (settings.get('UI_Use_Real_Name') && user.name) || user.username }: ${ notificationMessage }`,
};
}

return { title, text };
return {
title: (settings.get('UI_Use_Real_Name') && user.name) || user.username,
text: notificationMessage,
};
}

getAvatarPath(roomData, subData) {
Expand Down
6 changes: 6 additions & 0 deletions app/lib/server/functions/addUserToRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import { Meteor } from 'meteor/meteor';

import { Rooms, Subscriptions, Messages } from '../../../models';
import { callbacks } from '../../../callbacks';
import { roomTypes, RoomMemberActions } from '../../../utils/server';

export const addUserToRoom = function(rid, user, inviter, silenced) {
const now = new Date();
const room = Rooms.findOneById(rid);

const roomConfig = roomTypes.getConfig(room.t);
if (!roomConfig.allowMemberAction(room, RoomMemberActions.JOIN) && !roomConfig.allowMemberAction(room, RoomMemberActions.INVITE)) {
return;
}

// Check if user is already in room
const subscription = Subscriptions.findOneByRoomIdAndUserId(rid, user._id);
if (subscription) {
Expand Down
29 changes: 19 additions & 10 deletions app/lib/server/functions/deleteUser.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { Meteor } from 'meteor/meteor';
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';

import { FileUpload } from '../../../file-upload';
import { FileUpload } from '../../../file-upload/server';
import { Users, Subscriptions, Messages, Rooms, Integrations, FederationServers } from '../../../models/server';
import { hasRole, getUsersInRole } from '../../../authorization/server';
import { settings } from '../../../settings/server';
import { Notifications } from '../../../notifications/server';
import { updateGroupDMsName } from './updateGroupDMsName';

const bulkRoomCleanUp = (rids) => {
// no bulk deletion for files
rids.forEach((rid) => FileUpload.removeFilesByRoomId(rid));

return Promise.await(Promise.all([
Subscriptions.removeByRoomIds(rids),
Messages.removeByRoomIds(rids),
Rooms.removeByIds(rids),
]));
};

export const deleteUser = function(userId) {
const user = Users.findOneById(userId, {
fields: { username: 1, avatarOrigin: 1, federation: 1 },
Expand Down Expand Up @@ -83,21 +94,19 @@ export const deleteUser = function(userId) {
break;
}

roomCache.forEach((roomData) => {
const roomIds = roomCache.filter((roomData) => {
if (roomData.subscribers === null && roomData.t !== 'd' && roomData.t !== 'c') {
roomData.subscribers = Subscriptions.findByRoomId(roomData.rid).count();
}

// Remove non-channel rooms with only 1 user (the one being deleted)
if (roomData.t !== 'c' && roomData.subscribers === 1) {
Subscriptions.removeByRoomId(roomData.rid);
FileUpload.removeFilesByRoomId(roomData.rid);
Messages.removeByRoomId(roomData.rid);
Rooms.removeById(roomData.rid);
}
});
return roomData.t !== 'c' && roomData.subscribers === 1;
}).map(({ _id }) => _id);

Rooms.find1On1ByUserId(user._id, { fields: { _id: 1 } }).forEach(({ _id }) => roomIds.push(_id));

bulkRoomCleanUp(roomIds);

// TODO: do not remove group DMs
Rooms.updateGroupDMsRemovingUsernamesByUsername(user.username); // Remove direct rooms with the user
Rooms.removeDirectRoomContainingUsername(user.username); // Remove direct rooms with the user

Expand Down
8 changes: 5 additions & 3 deletions app/lib/server/functions/notifications/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ function getEmailContent({ message, user, room }) {
const roomName = s.escapeHTML(`#${ roomTypes.getRoomName(room.t, room) }`);
const userName = s.escapeHTML(settings.get('UI_Use_Real_Name') ? message.u.name || message.u.username : message.u.username);

const header = TAPi18n.__(room.t === 'd' ? 'User_sent_a_message_to_you' : 'User_sent_a_message_on_channel', {
const roomType = roomTypes.getConfig(room.t);

const header = TAPi18n.__(!roomType.isGroupChat(room) ? 'User_sent_a_message_to_you' : 'User_sent_a_message_on_channel', {
username: userName,
channel: roomName,
lng,
Expand Down Expand Up @@ -54,7 +56,7 @@ function getEmailContent({ message, user, room }) {
}

if (message.file) {
const fileHeader = TAPi18n.__(room.t === 'd' ? 'User_uploaded_a_file_to_you' : 'User_uploaded_a_file_on_channel', {
const fileHeader = TAPi18n.__(!roomType.isGroupChat(room) ? 'User_uploaded_a_file_to_you' : 'User_uploaded_a_file_on_channel', {
username: userName,
channel: roomName,
lng,
Expand Down Expand Up @@ -112,7 +114,7 @@ export function sendEmail({ message, user, subscription, room, emailAddress, has
const username = settings.get('UI_Use_Real_Name') ? message.u.name || message.u.username : message.u.username;
let subjectKey = 'Offline_Mention_All_Email';

if (room.t === 'd') {
if (!roomTypes.getConfig(room.t).isGroupChat(room)) {
subjectKey = 'Offline_DM_Email';
} else if (hasMentionToUser) {
subjectKey = 'Offline_Mention_Email';
Expand Down
2 changes: 1 addition & 1 deletion app/lib/server/functions/notifications/mobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export async function sendSinglePush({ room, message, userId, receiverUsername,
messageType: message.t,
messageId: message._id,
},
roomName: settings.get('Push_show_username_room') && room.t !== 'd' ? `#${ roomTypes.getRoomName(room.t, room) }` : '',
roomName: settings.get('Push_show_username_room') && roomTypes.getConfig(room.t).isGroupChat(room) ? `#${ roomTypes.getRoomName(room.t, room) }` : '',
username,
message: settings.get('Push_show_message') ? notificationMessage : ' ',
badge: await getBadgeCount(userId),
Expand Down
4 changes: 4 additions & 0 deletions app/models/server/models/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,10 @@ export class Messages extends Base {
return this.remove(query);
}

removeByRoomIds(rids) {
return this.remove({ rid: { $in: rids } });
}

removeByIdPinnedTimestampLimitAndUsers(rid, pinned, ignoreDiscussion = true, ts, limit, users = []) {
const query = {
rid,
Expand Down
31 changes: 24 additions & 7 deletions app/models/server/models/Rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class Rooms extends Base {
this.tryEnsureIndex({ ts: 1 });
// discussions
this.tryEnsureIndex({ prid: 1 }, { sparse: true });
this.tryEnsureIndex({ fname: 1 }, { sparse: true });
// Livechat - statistics
this.tryEnsureIndex({ closedAt: 1 }, { sparse: true });

Expand Down Expand Up @@ -414,6 +415,20 @@ export class Rooms extends Base {
return this._db.find(query, options);
}

findByNameOrFNameAndType(name, type, options) {
const query = {
t: type,
$or: [{
name,
}, {
fname: name,
}],
};

// do not use cache
return this._db.find(query, options);
}

findByNameAndTypeNotDefault(name, type, options) {
const query = {
t: type,
Expand Down Expand Up @@ -550,6 +565,13 @@ export class Rooms extends Base {
}, options);
}

find1On1ByUserId(userId, options) {
return this.find({
uids: userId,
usersCount: 2,
}, options);
}

// UPDATE
addImportIds(_id, importIds) {
importIds = [].concat(importIds);
Expand Down Expand Up @@ -1025,13 +1047,8 @@ export class Rooms extends Base {
return this.remove(query);
}

remove1on1ById(_id) {
const query = {
_id,
usersCount: { $lte: 2 },
};

return this.remove(query);
removeByIds(ids) {
return this.remove({ _id: { $in: ids } });
}

removeDirectRoomContainingUsername(username) {
Expand Down
4 changes: 4 additions & 0 deletions app/models/server/models/Subscriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,10 @@ export class Subscriptions extends Base {
return result;
}

removeByRoomIds(rids) {
return this.remove({ rid: { $in: rids } });
}

// //////////////////////////////////////////////////////////////////
// threads

Expand Down
6 changes: 3 additions & 3 deletions app/ui-flextab/client/tabs/membersList.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@
<div class="rc-button__group rc-button__group--stretch">
{{#if canAddUser}}
<button class="rc-button rc-button--primary js-add">{{> icon block="rc-input__icon-svg" icon="plus"}}{{_ "Add_users"}}</button>
{{/if}}

{{#if canInviteUser}}
<button class="rc-button rc-button--primary js-invite">{{> icon block="rc-input__icon-svg" icon="user-plus"}}{{_ "Invite_Users"}}</button>
{{#if canInviteUser}}
<button class="rc-button rc-button--primary js-invite">{{> icon block="rc-input__icon-svg" icon="user-plus"}}{{_ "Invite_Users"}}</button>
{{/if}}
{{/if}}
</div>

Expand Down
1 change: 1 addition & 0 deletions app/ui-sidenav/client/chatRoomItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Template.chatRoomItem.helpers({
active: false,
archivedClass,
status: this.t === 'd' || this.t === 'l',
isGroupChat: roomType.isGroupChat(room),
};
roomData.username = roomData.username || roomData.name;

Expand Down
2 changes: 1 addition & 1 deletion app/ui-sidenav/client/sidebarItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Template.sidebarItem.onCreated(function() {
const renderedMessage = renderMessageBody(currentData.lastMessage).replace(/<br\s?\\?>/g, ' ');
const sender = this.user && this.user._id === currentData.lastMessage.u._id ? t('You') : otherUser;

if (currentData.t === 'd' && Meteor.userId() !== currentData.lastMessage.u._id) {
if (!currentData.isGroupChat && Meteor.userId() !== currentData.lastMessage.u._id) {
this.renderedMessage = currentData.lastMessage.msg === '' ? t('Sent_an_attachment') : renderedMessage;
} else {
this.renderedMessage = currentData.lastMessage.msg === '' ? t('user_sent_an_attachment', { user: sender }) : `${ sender }: ${ renderedMessage }`;
Expand Down
6 changes: 3 additions & 3 deletions app/ui/client/views/app/components/Directory/ChannelsTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ export function ChannelsTab() {
}, []);

const formatDate = useFormatDate();
const renderRow = useCallback(({ _id, ts, default: d, name, description, usersCount, lastMessage, topic }) => <Table.Row key={_id} onKeyDown={onClick(name)} onClick={onClick(name)} tabIndex={0} role='link' action>
const renderRow = useCallback(({ _id, ts, default: d, name, fname, description, usersCount, lastMessage, topic }) => <Table.Row key={_id} onKeyDown={onClick(name)} onClick={onClick(name)} tabIndex={0} role='link' action>
<Table.Cell>
<Flex.Container>
<Box>
<Flex.Item>
<Box>
<Avatar size='x40' title={name} url={`%40${ name }`} />
<Avatar size='x40' title={fname || name} url={`%40${ fname || name }`} />
</Box>
</Flex.Item>
<Margins inline='x8'>
<Flex.Item grow={1}>
<Box>
<Box textStyle='p2'>{name} {d && <Tag variant='primary'>{t('default')}</Tag>}</Box>
<Box textStyle='p2'>{fname || name} {d && <Tag variant='primary'>{t('default')}</Tag>}</Box>
{description && <Box textStyle='p1' textColor='hint'>{description}</Box> }
</Box>
</Flex.Item>
Expand Down
6 changes: 3 additions & 3 deletions client/components/admin/info/InformationRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function InformationRoute() {
useEffect(() => {
let didCancel = false;

const fetchStatistics = async () => {
const fetchStatistics = async ({ refresh = false } = {}) => {
if (!canViewStatistics) {
setStatistics(null);
setInstances(null);
Expand All @@ -32,7 +32,7 @@ export function InformationRoute() {

try {
const [statistics, instances] = await Promise.all([
getStatistics({ refresh: true }),
getStatistics({ refresh }),
getInstances(),
]);

Expand Down Expand Up @@ -62,7 +62,7 @@ export function InformationRoute() {
return;
}

fetchStatistics();
fetchStatistics({ refresh: true });
};

const handleClickDownloadInfo = () => {
Expand Down
3 changes: 2 additions & 1 deletion server/methods/browseChannels.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,14 @@ Meteor.methods({
return;
}

const result = Rooms.findByNameAndType(regex, 'c', {
const result = Rooms.findByNameOrFNameAndType(regex, 'c', {
...pagination,
sort,
fields: {
description: 1,
topic: 1,
name: 1,
fname: 1,
lastMessage: 1,
ts: 1,
archived: 1,
Expand Down

0 comments on commit 55227d3

Please sign in to comment.