Skip to content

Commit

Permalink
Merge branch 'feat/CS-19-connectivity-services' into CS-313-use-works…
Browse files Browse the repository at this point in the history
…pace-token-instead-of-user-token-for-modals
  • Loading branch information
geekgonecrazy authored Feb 3, 2023
2 parents f34ce0a + bedfce7 commit 2c16961
Show file tree
Hide file tree
Showing 179 changed files with 2,851 additions and 1,551 deletions.
2 changes: 1 addition & 1 deletion apps/meteor/app/apps/client/communication/websockets.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor';
import { Emitter } from '@rocket.chat/emitter';

import { slashCommands, APIClient } from '../../../utils';
import { CachedCollectionManager } from '../../../ui-cached-collection';
import { CachedCollectionManager } from '../../../ui-cached-collection/client';
import { loadButtons } from '../../../ui-message/client/ActionButtonSyncer';

export const AppEvents = Object.freeze({
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/apps/client/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { AppScreenshot, AppRequestFilter, Pagination, IRestResponse, Serial
import type { App } from '../../../client/views/admin/apps/types';
import { dispatchToastMessage } from '../../../client/lib/toast';
import { settings } from '../../settings/client';
import { CachedCollectionManager } from '../../ui-cached-collection';
import { CachedCollectionManager } from '../../ui-cached-collection/client';
import { createDeferredValue } from '../lib/misc/DeferredValue';
import type {
// IAppFromMarketplace,
Expand Down
7 changes: 7 additions & 0 deletions apps/meteor/app/apps/server/communication/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Apps } from '../orchestrator';
import { formatAppInstanceForRest } from '../../lib/misc/formatAppInstanceForRest';
import { actionButtonsHandler } from './endpoints/actionButtonsHandler';
import { fetch } from '../../../../server/lib/http/fetch';
import { notifyAppInstall } from '../marketplace/appInstall';

const rocketChatVersion = Info.version;
const appsEngineVersionForMarketplace = Info.marketplaceApiVersion.replace(/-.*/g, '');
Expand Down Expand Up @@ -273,6 +274,8 @@ export class AppsRestApi {

info.status = aff.getApp().getStatus();

notifyAppInstall(orchestrator.getMarketplaceUrl(), 'install', info);

return API.v1.success({
app: info,
implemented: aff.getImplementedInferfaces(),
Expand Down Expand Up @@ -558,6 +561,8 @@ export class AppsRestApi {

info.status = aff.getApp().getStatus();

notifyAppInstall(orchestrator.getMarketplaceUrl(), 'update', info);

return API.v1.success({
app: info,
implemented: aff.getImplementedInferfaces(),
Expand All @@ -578,6 +583,8 @@ export class AppsRestApi {
const info = prl.getInfo();
info.status = prl.getStatus();

notifyAppInstall(orchestrator.getMarketplaceUrl(), 'uninstall', info);

return API.v1.success({ app: info });
},
},
Expand Down
46 changes: 46 additions & 0 deletions apps/meteor/app/apps/server/marketplace/appInstall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';

import { getWorkspaceAccessToken } from '../../../cloud/server';
import { settings } from '../../../settings/server';
import { Info } from '../../../utils/server';

export type installAction = 'install' | 'update' | 'uninstall';

export async function notifyAppInstall(marketplaceBaseUrl: string, action: installAction, appInfo: IAppInfo): Promise<void> {
const headers: { Authorization?: string } = {};

try {
const token = await getWorkspaceAccessToken();
headers.Authorization = `Bearer ${token}`;

// eslint-disable-next-line no-empty
} catch {}

let siteUrl = '';
try {
siteUrl = settings.get<string>('Site_Url');

// eslint-disable-next-line no-empty
} catch {}

const data = {
action,
appName: appInfo.name,
appSlug: appInfo.nameSlug,
appVersion: appInfo.version,
rocketChatVersion: Info.version,
engineVersion: Info.marketplaceApiVersion,
siteUrl,
};

const pendingSentUrl = `${marketplaceBaseUrl}/v1/apps/${appInfo.id}/install`;

try {
HTTP.post(pendingSentUrl, {
headers,
data,
});

// eslint-disable-next-line no-empty
} catch {}
}
19 changes: 15 additions & 4 deletions apps/meteor/app/authorization/client/hasPermission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { ChatPermissions } from './lib/ChatPermissions';
import * as Models from '../../models/client';
import { AuthorizationUtils } from '../lib/AuthorizationUtils';

const isValidScope = (scope: IRole['scope']): boolean => typeof scope === 'string' && scope in Models;
const isValidScope = (scope: unknown): scope is keyof typeof Models => typeof scope === 'string' && scope in Models;

const hasIsUserInRole = (
model: unknown,
): model is {
isUserInRole: (this: any, uid: IUser['_id'], roleId: IRole['_id'], scope: string | undefined) => boolean;
} => typeof model === 'object' && model !== null && typeof (model as { isUserInRole?: unknown }).isUserInRole === 'function';

const createPermissionValidator =
(quantifier: (predicate: (permissionId: IPermission['_id']) => boolean) => boolean) =>
Expand All @@ -21,7 +27,7 @@ const createPermissionValidator =
}
}

const permission: IPermission | null = ChatPermissions.findOne(permissionId, {
const permission = ChatPermissions.findOne(permissionId, {
fields: { roles: 1 },
});
const roles = permission?.roles ?? [];
Expand All @@ -34,8 +40,13 @@ const createPermissionValidator =
return false;
}

const model = Models[roleScope as keyof typeof Models];
return model.isUserInRole?.(userId, roleId, scope);
const model = Models[roleScope];

if (hasIsUserInRole(model)) {
return model.isUserInRole(userId, roleId, scope);
}

return undefined;
});
});
};
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/authorization/client/startup.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

import { CachedCollectionManager } from '../../ui-cached-collection';
import { CachedCollectionManager } from '../../ui-cached-collection/client';
import { APIClient } from '../../utils/client/lib/RestApiClient';
import { Roles } from '../../models/client';
import { rolesStreamer } from './lib/streamer';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
export const getSettingPermissionId = function (settingId) {
import type { ISetting } from '@rocket.chat/core-typings';

export const getSettingPermissionId = function (settingId: ISetting['_id']) {
// setting-based permissions
return `change-setting-${settingId}`;
};

export const CONSTANTS = {
SETTINGS_LEVEL: 'settings',
};
} as const;

export { AuthorizationUtils } from './AuthorizationUtils';
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,12 @@ export const upsertPermissions = async (): Promise<void> => {
},
): Promise<void> {
const permissionId = getSettingPermissionId(setting._id);
const permission: Omit<IPermission, '_id'> = {
const permission: Omit<IPermission, '_id' | '_updatedAt'> = {
level: CONSTANTS.SETTINGS_LEVEL as 'settings' | undefined,
// copy those setting-properties which are needed to properly publish the setting-based permissions
settingId: setting._id,
group: setting.group,
section: setting.section,
section: setting.section ?? undefined,
sorter: setting.sorter,
roles: [],
};
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/app/custom-sounds/client/lib/CustomSounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor';
import { ReactiveVar } from 'meteor/reactive-var';
import _ from 'underscore';

import { CachedCollectionManager } from '../../../ui-cached-collection';
import { CachedCollectionManager } from '../../../ui-cached-collection/client';
import { getURL } from '../../../utils/client';

const getCustomSoundId = (sound) => `custom-sound-${sound}`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import { CachedCollectionManager } from '../../../ui-cached-collection';
import { CachedCollectionManager } from '../../../ui-cached-collection/client';
import { Notifications } from '../../../notifications';
import { CustomSounds } from '../lib/CustomSounds';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import { CachedCollectionManager } from '../../../ui-cached-collection';
import { CachedCollectionManager } from '../../../ui-cached-collection/client';
import { Notifications } from '../../../notifications';
import { CustomSounds } from '../lib/CustomSounds';

Expand Down
10 changes: 5 additions & 5 deletions apps/meteor/app/e2e/client/rocketchat.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { ReactiveVar as ReactiveVarType } from 'meteor/reactive-var';
import { EJSON } from 'meteor/ejson';
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
import { Emitter } from '@rocket.chat/emitter';
import type { IE2EEMessage, IMessage, IRoom } from '@rocket.chat/core-typings';
import type { IE2EEMessage, IMessage, IRoom, ISubscription } from '@rocket.chat/core-typings';
import { isE2EEMessage } from '@rocket.chat/core-typings';

import { getMessageUrlRegex } from '../../../lib/getMessageUrlRegex';
Expand Down Expand Up @@ -447,16 +447,16 @@ class E2E extends Emitter {
});
}

async decryptSubscription(rid: IRoom['_id']): Promise<void> {
const e2eRoom = await this.getInstanceByRoomId(rid);
this.log('decryptSubscription ->', rid);
async decryptSubscription(subscriptionId: ISubscription['_id']): Promise<void> {
const e2eRoom = await this.getInstanceByRoomId(subscriptionId);
this.log('decryptSubscription ->', subscriptionId);
e2eRoom?.decryptSubscription();
}

async decryptSubscriptions(): Promise<void> {
Subscriptions.find({
encrypted: true,
}).forEach((room: IRoom) => this.decryptSubscription(room._id));
}).forEach((subscription) => this.decryptSubscription(subscription._id));
}

openAlert(config: Omit<LegacyBannerPayload, 'id'>): void {
Expand Down
27 changes: 23 additions & 4 deletions apps/meteor/app/lib/server/lib/notifyUsersOnMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ export function getMentions(message) {

const incGroupMentions = (rid, roomType, excludeUserId, unreadCount) => {
const incUnreadByGroup = ['all_messages', 'group_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount);
const incUnread = roomType === 'd' || incUnreadByGroup ? 1 : 0;
const incUnread = roomType === 'd' || roomType === 'l' || incUnreadByGroup ? 1 : 0;

Subscriptions.incGroupMentionsAndUnreadForRoomIdExcludingUserId(rid, excludeUserId, 1, incUnread);
};

const incUserMentions = (rid, roomType, uids, unreadCount) => {
const incUnreadByUser = ['all_messages', 'user_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount);
const incUnread = roomType === 'd' || incUnreadByUser ? 1 : 0;
const incUnread = roomType === 'd' || roomType === 'l' || incUnreadByUser ? 1 : 0;

Subscriptions.incUserMentionsAndUnreadForRoomIdAndUserIds(rid, uids, 1, incUnread);
};
Expand All @@ -86,15 +86,34 @@ const getUserIdsFromHighlights = (rid, message) => {
.map(({ u: { _id: uid } }) => uid);
};

/*
* {IRoom['t']} roomType - The type of the room
* @returns {string} - The setting value for unread count
*/
const getUnreadSettingCount = (roomType) => {
let unreadSetting = 'Unread_Count';
switch (roomType) {
case 'd': {
unreadSetting = 'Unread_Count_DM';
break;
}
case 'l': {
unreadSetting = 'Unread_Count_Omni';
break;
}
}

return settings.get(unreadSetting);
};

export async function updateUsersSubscriptions(message, room) {
// Don't increase unread counter on thread messages
if (room != null && !message.tmid) {
const { toAll, toHere, mentionIds } = getMentions(message);

const userIds = new Set(mentionIds);

const unreadSetting = room.t === 'd' ? 'Unread_Count_DM' : 'Unread_Count';
const unreadCount = settings.get(unreadSetting);
const unreadCount = getUnreadSettingCount(room.t);

getUserIdsFromHighlights(room._id, message).forEach((uid) => userIds.add(uid));

Expand Down
14 changes: 14 additions & 0 deletions apps/meteor/app/lib/server/startup/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,20 @@ settingsRegistry.addGroup('General', function () {
],
public: true,
});
this.add('Unread_Count_Omni', 'all_messages', {
type: 'select',
values: [
{
key: 'all_messages',
i18nLabel: 'All_messages',
},
{
key: 'mentions_only',
i18nLabel: 'Mentions_only',
},
],
public: true,
});

this.add('DeepLink_Url', 'https://go.rocket.chat', {
type: 'string',
Expand Down
48 changes: 27 additions & 21 deletions apps/meteor/app/models/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { Meteor } from 'meteor/meteor';
import _ from 'underscore';

import { Base } from './models/_Base';
import { Base } from './models/Base';
import Avatars from './models/Avatars';
import Uploads from './models/Uploads';
import UserDataFiles from './models/UserDataFiles';
import { Roles } from './models/Roles';
import { Subscriptions as subscriptions } from './models/Subscriptions';
import { Users as users } from './models/Users';
import { Users } from './models/Users';
import { CachedChannelList } from './models/CachedChannelList';
import { CachedChatRoom } from './models/CachedChatRoom';
import { CachedChatSubscription } from './models/CachedChatSubscription';
Expand All @@ -23,38 +19,48 @@ import { WebdavAccounts } from './models/WebdavAccounts';
import CustomSounds from './models/CustomSounds';
import EmojiCustom from './models/EmojiCustom';

/** @deprecated */
const Users = _.extend({}, users, Meteor.users);
/** @deprecated */
const Subscriptions = _.extend({}, subscriptions, ChatSubscription);
/** @deprecated */
const Messages = _.extend({}, ChatMessage) as typeof ChatMessage;
/** @deprecated */
const Rooms = _.extend({}, ChatRoom) as typeof ChatRoom;
// overwrite Meteor.users collection so records on it don't get erased whenever the client reconnects to websocket
Meteor.users = Users as typeof Meteor.users;
Meteor.user = () => {
const uid = Meteor.userId();

if (!uid) {
return null;
}

return (Users.findOne({ _id: uid }) ?? null) as Meteor.User | null;
};

export {
Base,
Avatars,
Uploads,
UserDataFiles,
Roles,
Subscriptions,
Users,
Messages,
CachedChannelList,
CachedChatRoom,
CachedChatSubscription,
CachedUserList,
ChatRoom,
RoomRoles,
UserAndRoom,
UserRoles,
AuthzCachedCollection,
ChatPermissions,
ChatMessage,
ChatSubscription,
Rooms,
CustomSounds,
EmojiCustom,
WebdavAccounts,
/** @deprecated */
Users,
/** @deprecated */
ChatRoom as Rooms,
/** @deprecated */
ChatRoom,
/** @deprecated */
ChatSubscription,
/** @deprecated */
ChatSubscription as Subscriptions,
/** @deprecated */
ChatMessage,
/** @deprecated */
ChatMessage as Messages,
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Base } from './_Base';
import { Base } from './Base';

export class Avatars extends Base {
constructor() {
Expand Down
Loading

0 comments on commit 2c16961

Please sign in to comment.