Skip to content

Commit

Permalink
Chore: Migrate cached collections to TypeScript (#27909)
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan authored Feb 1, 2023
1 parent 8e91073 commit 536eb15
Show file tree
Hide file tree
Showing 92 changed files with 1,230 additions and 1,020 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
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
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
64 changes: 64 additions & 0 deletions apps/meteor/app/models/client/models/Base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { check } from 'meteor/check';
import { Mongo } from 'meteor/mongo';

export abstract class Base<T = any> {
private model: Mongo.Collection<T>;

protected _baseName() {
return 'rocketchat_';
}

protected _initModel(name: string) {
check(name, String);
this.model = new Mongo.Collection(this._baseName() + name);
return this.model;
}

find(...args: Parameters<Mongo.Collection<T>['find']>) {
return this.model.find(...args);
}

findOne(...args: Parameters<Mongo.Collection<T>['findOne']>) {
return this.model.findOne(...args);
}

insert(...args: Parameters<Mongo.Collection<T>['insert']>) {
return this.model.insert(...args);
}

update(...args: Parameters<Mongo.Collection<T>['update']>) {
return this.model.update(...args);
}

upsert(...args: Parameters<Mongo.Collection<T>['upsert']>) {
return this.model.upsert(...args);
}

remove(...args: Parameters<Mongo.Collection<T>['remove']>) {
return this.model.remove(...args);
}

allow(...args: Parameters<Mongo.Collection<T>['allow']>) {
return this.model.allow(...args);
}

deny(...args: Parameters<Mongo.Collection<T>['deny']>) {
return this.model.deny(...args);
}

ensureIndex() {
// do nothing
}

dropIndex() {
// do nothing
}

tryEnsureIndex() {
// do nothing
}

tryDropIndex() {
// do nothing
}
}
3 changes: 0 additions & 3 deletions apps/meteor/app/models/client/models/CachedChannelList.js

This file was deleted.

4 changes: 4 additions & 0 deletions apps/meteor/app/models/client/models/CachedChannelList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type { IRoom } from '@rocket.chat/core-typings';
import { Mongo } from 'meteor/mongo';

export const CachedChannelList = new Mongo.Collection<IRoom>(null);
3 changes: 0 additions & 3 deletions apps/meteor/app/models/client/models/CachedChatRoom.js

This file was deleted.

Loading

0 comments on commit 536eb15

Please sign in to comment.