diff --git a/packages/rocketchat-grant/server/grant.js b/packages/rocketchat-grant/server/grant.js index 7cb9e29b63d9..b6a6e1d41885 100644 --- a/packages/rocketchat-grant/server/grant.js +++ b/packages/rocketchat-grant/server/grant.js @@ -1,5 +1,4 @@ -import { RocketChat } from 'meteor/rocketchat:lib'; - +import { hostname } from 'meteor/rocketchat:lib'; import Providers from './providers'; import Settings from './settings'; import { path, generateCallback, generateAppCallback } from './routes'; @@ -38,7 +37,7 @@ const config = {}; export function generateConfig() { config.server = { protocol: 'http', - host: RocketChat.hostname, + host: hostname, path, state: true, }; diff --git a/packages/rocketchat-lib/client/lib/openRoom.js b/packages/rocketchat-lib/client/lib/openRoom.js index 2ba6f4b4788f..e44424c18a83 100644 --- a/packages/rocketchat-lib/client/lib/openRoom.js +++ b/packages/rocketchat-lib/client/lib/openRoom.js @@ -1,102 +1,3 @@ -import { Meteor } from 'meteor/meteor'; -import { Tracker } from 'meteor/tracker'; -import { FlowRouter } from 'meteor/kadira:flow-router'; -import { BlazeLayout } from 'meteor/kadira:blaze-layout'; -import { Session } from 'meteor/session'; -import { RoomManager, fireGlobalEvent, readMessage, RoomHistoryManager, Layout } from 'meteor/rocketchat:ui-utils'; -import { ChatSubscription, Rooms } from 'meteor/rocketchat:models'; -import { settings } from 'meteor/rocketchat:settings'; -import { callbacks } from 'meteor/rocketchat:callbacks'; -import { roomTypes, handleError } from 'meteor/rocketchat:utils'; -import _ from 'underscore'; +import { openRoom as _openRoom } from 'meteor/rocketchat:ui-utils'; -export let currentTracker = undefined; - -openRoom = function(type, name) { - Session.set('openedRoom', null); - - return Meteor.defer(() => - currentTracker = Tracker.autorun(function(c) { - const user = Meteor.user(); - if ((user && user.username == null) || (user == null && settings.get('Accounts_AllowAnonymousRead') === false)) { - BlazeLayout.render('main'); - return; - } - - if (RoomManager.open(type + name).ready() !== true) { - BlazeLayout.render('main', { modal: Layout.isEmbedded(), center: 'loading' }); - return; - } - if (currentTracker) { - currentTracker = undefined; - } - c.stop(); - - const room = roomTypes.findRoom(type, name, user); - if (room == null) { - if (type === 'd') { - Meteor.call('createDirectMessage', name, function(error) { - if (!error) { - RoomManager.close(type + name); - return openRoom('d', name); - } else { - Session.set('roomNotFound', { type, name, error }); - BlazeLayout.render('main', { center: 'roomNotFound' }); - return; - } - }); - } else { - Meteor.call('getRoomByTypeAndName', type, name, function(error, record) { - if (error) { - Session.set('roomNotFound', { type, name, error }); - return BlazeLayout.render('main', { center: 'roomNotFound' }); - } else { - Rooms.upsert({ _id: record._id }, _.omit(record, '_id')); - RoomManager.close(type + name); - return openRoom(type, name); - } - }); - } - return; - } - - const mainNode = document.querySelector('.main-content'); - if (mainNode) { - for (const child of Array.from(mainNode.children)) { - if (child) { mainNode.removeChild(child); } - } - const roomDom = RoomManager.getDomOfRoom(type + name, room._id); - mainNode.appendChild(roomDom); - if (roomDom.classList.contains('room-container')) { - roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop; - } - } - - Session.set('openedRoom', room._id); - RoomManager.openedRoom = room._id; - - fireGlobalEvent('room-opened', _.omit(room, 'usernames')); - - Session.set('editRoomTitle', false); - RoomManager.updateMentionsMarksOfRoom(type + name); - Meteor.setTimeout(() => readMessage.readNow(), 2000); - // KonchatNotification.removeRoomNotification(params._id) - // update user's room subscription - const sub = ChatSubscription.findOne({ rid: room._id }); - if (sub && sub.open === false) { - Meteor.call('openRoom', room._id, function(err) { - if (err) { - return handleError(err); - } - }); - } - - if (FlowRouter.getQueryParam('msg')) { - const msg = { _id: FlowRouter.getQueryParam('msg'), rid: room._id }; - RoomHistoryManager.getSurroundingMessages(msg); - } - - return callbacks.run('enter-room', sub); - }) - ); -}; +openRoom = _openRoom; diff --git a/packages/rocketchat-lib/client/lib/roomExit.js b/packages/rocketchat-lib/client/lib/roomExit.js index 28bbfefa6c56..89139fc589bc 100644 --- a/packages/rocketchat-lib/client/lib/roomExit.js +++ b/packages/rocketchat-lib/client/lib/roomExit.js @@ -1,7 +1,7 @@ import { Blaze } from 'meteor/blaze'; import { BlazeLayout } from 'meteor/kadira:blaze-layout'; import { callbacks } from 'meteor/rocketchat:callbacks'; -import { currentTracker } from './openRoom'; +import { currentTracker } from 'meteor/rocketchat:ui-utils'; this.roomExit = function() { // 7370 - Close flex-tab when opening a room on mobile UI diff --git a/packages/rocketchat-lib/lib/Message.js b/packages/rocketchat-lib/lib/Message.js index dbe0c18470a2..01cffb19bb53 100644 --- a/packages/rocketchat-lib/lib/Message.js +++ b/packages/rocketchat-lib/lib/Message.js @@ -1,32 +1,3 @@ -import { TAPi18n } from 'meteor/tap:i18n'; -import s from 'underscore.string'; +import { Message } from 'meteor/rocketchat:ui-utils'; -RocketChat.Message = { - parse(msg, language) { - const messageType = RocketChat.MessageTypes.getType(msg); - if (messageType) { - if (messageType.render) { - return messageType.render(msg); - } else if (messageType.template) { - // Render message - return; - } else if (messageType.message) { - if (!language && typeof localStorage !== 'undefined') { - language = localStorage.getItem('userLanguage'); - } - const data = (typeof messageType.data === 'function' && messageType.data(msg)) || {}; - return TAPi18n.__(messageType.message, data, language); - } - } - if (msg.u && msg.u.username === RocketChat.settings.get('Chatops_Username')) { - msg.html = msg.msg; - return msg.html; - } - msg.html = msg.msg; - if (s.trim(msg.html) !== '') { - msg.html = s.escapeHTML(msg.html); - } - msg.html = msg.html.replace(/\n/gm, '
'); - return msg.html; - }, -}; +RocketChat.Message = Message; diff --git a/packages/rocketchat-lib/lib/MessageTypes.js b/packages/rocketchat-lib/lib/MessageTypes.js index 6e773f5d54ab..95fc06858614 100644 --- a/packages/rocketchat-lib/lib/MessageTypes.js +++ b/packages/rocketchat-lib/lib/MessageTypes.js @@ -1,10 +1,11 @@ import { Meteor } from 'meteor/meteor'; import { MessageTypes } from 'meteor/rocketchat:ui-utils'; +import { callbacks } from 'meteor/rocketchat:callbacks'; RocketChat.MessageTypes = MessageTypes; Meteor.startup(function() { - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'r', system: true, message: 'Room_name_changed', @@ -15,7 +16,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'au', system: true, message: 'User_added_by', @@ -26,7 +27,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'ru', system: true, message: 'User_removed_by', @@ -37,7 +38,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'ul', system: true, message: 'User_left', @@ -47,7 +48,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'uj', system: true, message: 'User_joined_channel', @@ -57,7 +58,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'wm', system: true, message: 'Welcome', @@ -67,7 +68,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'rm', system: true, message: 'Message_removed', @@ -77,13 +78,13 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'rtc', render(message) { - return RocketChat.callbacks.run('renderRtcMessage', message); + return callbacks.run('renderRtcMessage', message); }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'user-muted', system: true, message: 'User_muted_by', @@ -94,7 +95,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'user-unmuted', system: true, message: 'User_unmuted_by', @@ -105,7 +106,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'subscription-role-added', system: true, message: '__username__was_set__role__by__user_by_', @@ -117,7 +118,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'subscription-role-removed', system: true, message: '__username__is_no_longer__role__defined_by__user_by_', @@ -129,7 +130,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'room-archived', system: true, message: 'This_room_has_been_archived_by__username_', @@ -139,7 +140,7 @@ Meteor.startup(function() { }; }, }); - RocketChat.MessageTypes.registerType({ + MessageTypes.registerType({ id: 'room-unarchived', system: true, message: 'This_room_has_been_unarchived_by__username_', diff --git a/packages/rocketchat-lib/lib/core.js b/packages/rocketchat-lib/lib/core.js index 31abca0cce3d..54be4847bbd0 100644 --- a/packages/rocketchat-lib/lib/core.js +++ b/packages/rocketchat-lib/lib/core.js @@ -1,5 +1,4 @@ -import EventEmitter from 'wolfy87-eventemitter'; -RocketChat = new EventEmitter(); +RocketChat = {}; /* * Kick off the global namespace for RocketChat. * @namespace RocketChat diff --git a/packages/rocketchat-lib/lib/getAvatarColor.js b/packages/rocketchat-lib/lib/getAvatarColor.js index ccc93b345820..3e29088837b3 100644 --- a/packages/rocketchat-lib/lib/getAvatarColor.js +++ b/packages/rocketchat-lib/lib/getAvatarColor.js @@ -1,5 +1,3 @@ -const colors = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B']; +import { getAvatarColor } from 'meteor/rocketchat:utils'; -RocketChat.getAvatarColor = function(name) { - return colors[name.length % colors.length]; -}; +RocketChat.getAvatarColor = getAvatarColor; diff --git a/packages/rocketchat-lib/lib/getURL.js b/packages/rocketchat-lib/lib/getURL.js index 4948d6527245..572286bd8884 100644 --- a/packages/rocketchat-lib/lib/getURL.js +++ b/packages/rocketchat-lib/lib/getURL.js @@ -1,21 +1,3 @@ -import { Meteor } from 'meteor/meteor'; -import s from 'underscore.string'; +import { getURL } from 'meteor/rocketchat:utils'; -RocketChat.getURL = (path, { cdn = true, full = false } = {}) => { - const cdnPrefix = s.rtrim(s.trim(RocketChat.settings.get('CDN_PREFIX') || ''), '/'); - const pathPrefix = s.rtrim(s.trim(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''), '/'); - - let basePath; - - const finalPath = s.ltrim(s.trim(path), '/'); - - if (cdn && cdnPrefix !== '') { - basePath = cdnPrefix + pathPrefix; - } else if (full) { - return Meteor.absoluteUrl(finalPath); - } else { - basePath = pathPrefix; - } - - return `${ basePath }/${ finalPath }`; -}; +RocketChat.getURL = getURL; diff --git a/packages/rocketchat-lib/lib/getValidRoomName.js b/packages/rocketchat-lib/lib/getValidRoomName.js index e48a30e25b76..a24b42a00719 100644 --- a/packages/rocketchat-lib/lib/getValidRoomName.js +++ b/packages/rocketchat-lib/lib/getValidRoomName.js @@ -1,49 +1,3 @@ -import { Meteor } from 'meteor/meteor'; -import s from 'underscore.string'; +import { getValidRoomName } from 'meteor/rocketchat:utils'; -RocketChat.getValidRoomName = function getValidRoomName(displayName, rid = '') { - let slugifiedName = displayName; - - if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { - const room = RocketChat.models.Rooms.findOneByDisplayName(displayName); - if (room && room._id !== rid) { - if (room.archived) { - throw new Meteor.Error('error-archived-duplicate-name', `There's an archived channel with name ${ displayName }`, { function: 'RocketChat.getValidRoomName', channel_name: displayName }); - } else { - throw new Meteor.Error('error-duplicate-channel-name', `A channel with name '${ displayName }' exists`, { function: 'RocketChat.getValidRoomName', channel_name: displayName }); - } - } - slugifiedName = s.slugify(displayName); - } - - let nameValidation; - try { - nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`); - } catch (error) { - nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$'); - } - if (!nameValidation.test(slugifiedName)) { - throw new Meteor.Error('error-invalid-room-name', `${ slugifiedName } is not a valid room name.`, { - function: 'RocketChat.getValidRoomName', - channel_name: slugifiedName, - }); - } - - const room = RocketChat.models.Rooms.findOneByName(slugifiedName); - if (room && room._id !== rid) { - if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { - let tmpName = slugifiedName; - let next = 0; - while (RocketChat.models.Rooms.findOneByNameAndNotId(tmpName, rid)) { - tmpName = `${ slugifiedName }-${ ++next }`; - } - slugifiedName = tmpName; - } else if (room.archived) { - throw new Meteor.Error('error-archived-duplicate-name', `There's an archived channel with name ${ slugifiedName }`, { function: 'RocketChat.getValidRoomName', channel_name: slugifiedName }); - } else { - throw new Meteor.Error('error-duplicate-channel-name', `A channel with name '${ slugifiedName }' exists`, { function: 'RocketChat.getValidRoomName', channel_name: slugifiedName }); - } - } - - return slugifiedName; -}; +RocketChat.getValidRoomName = getValidRoomName; diff --git a/packages/rocketchat-lib/lib/placeholders.js b/packages/rocketchat-lib/lib/placeholders.js index 45f996e86173..ae636d79c21e 100644 --- a/packages/rocketchat-lib/lib/placeholders.js +++ b/packages/rocketchat-lib/lib/placeholders.js @@ -1,32 +1,3 @@ -import s from 'underscore.string'; +import { placeholders } from 'meteor/rocketchat:utils'; -RocketChat.placeholders = {}; - -RocketChat.placeholders.replace = function(str, data) { - if (!str) { - return ''; - } - - str = str.replace(/\[Site_Name\]/g, RocketChat.settings.get('Site_Name') || ''); - str = str.replace(/\[Site_URL\]/g, RocketChat.settings.get('Site_Url') || ''); - - if (data) { - str = str.replace(/\[name\]/g, data.name || ''); - str = str.replace(/\[fname\]/g, s.strLeft(data.name, ' ') || ''); - str = str.replace(/\[lname\]/g, s.strRightBack(data.name, ' ') || ''); - str = str.replace(/\[email\]/g, data.email || ''); - str = str.replace(/\[password\]/g, data.password || ''); - str = str.replace(/\[reason\]/g, data.reason || ''); - str = str.replace(/\[User\]/g, data.user || ''); - str = str.replace(/\[Room\]/g, data.room || ''); - - if (data.unsubscribe) { - str = str.replace(/\[unsubscribe\]/g, data.unsubscribe); - } - } - - str = str.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2'); - - - return str; -}; +RocketChat.placeholders = placeholders; diff --git a/packages/rocketchat-lib/lib/roomTypes/conversation.js b/packages/rocketchat-lib/lib/roomTypes/conversation.js index 8f18930c5c68..66d737861d05 100644 --- a/packages/rocketchat-lib/lib/roomTypes/conversation.js +++ b/packages/rocketchat-lib/lib/roomTypes/conversation.js @@ -1,4 +1,5 @@ import { Meteor } from 'meteor/meteor'; +import { getUserPreference } from 'meteor/rocketchat:utils'; import { RoomTypeConfig } from '../RoomTypeConfig'; export class ConversationRoomType extends RoomTypeConfig { @@ -12,6 +13,6 @@ export class ConversationRoomType extends RoomTypeConfig { condition() { // returns true only if sidebarGroupByType is not set - return !RocketChat.getUserPreference(Meteor.userId(), 'sidebarGroupByType'); + return !getUserPreference(Meteor.userId(), 'sidebarGroupByType'); } } diff --git a/packages/rocketchat-lib/lib/roomTypes/direct.js b/packages/rocketchat-lib/lib/roomTypes/direct.js index a259f09db136..3530f4a1930a 100644 --- a/packages/rocketchat-lib/lib/roomTypes/direct.js +++ b/packages/rocketchat-lib/lib/roomTypes/direct.js @@ -1,7 +1,11 @@ import { Meteor } from 'meteor/meteor'; import { Session } from 'meteor/session'; +import { ChatRoom, Subscriptions } from 'meteor/rocketchat:models'; +import { openRoom } from 'meteor/rocketchat:ui-utils'; +import { getUserPreference } from 'meteor/rocketchat:utils'; +import { hasPermission, hasAtLeastOnePermission } from 'meteor/rocketchat:authorization'; +import { settings } from 'meteor/rocketchat:settings'; import { RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, UiTextContext } from '../RoomTypeConfig'; -import { ChatRoom } from 'meteor/rocketchat:models'; export class DirectMessageRoomRoute extends RoomTypeRouteConfig { constructor() { @@ -31,7 +35,7 @@ export class DirectMessageRoomType extends RoomTypeConfig { } findRoom(identifier) { - if (!RocketChat.authz.hasPermission('view-d-room')) { + if (!hasPermission('view-d-room')) { return null; } @@ -40,19 +44,19 @@ export class DirectMessageRoomType extends RoomTypeConfig { name: identifier, }; - const subscription = RocketChat.models.Subscriptions.findOne(query); + const subscription = Subscriptions.findOne(query); if (subscription && subscription.rid) { return ChatRoom.findOne(subscription.rid); } } roomName(roomData) { - const subscription = RocketChat.models.Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1, fname: 1 } }); + const subscription = Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1, fname: 1 } }); if (!subscription) { return ''; } - if (RocketChat.settings.get('UI_Use_Real_Name') && subscription.fname) { + if (settings.get('UI_Use_Real_Name') && subscription.fname) { return subscription.fname; } @@ -60,19 +64,19 @@ export class DirectMessageRoomType extends RoomTypeConfig { } secondaryRoomName(roomData) { - if (RocketChat.settings.get('UI_Use_Real_Name')) { - const subscription = RocketChat.models.Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } }); + if (settings.get('UI_Use_Real_Name')) { + const subscription = Subscriptions.findOne({ rid: roomData._id }, { fields: { name: 1 } }); return subscription && subscription.name; } } condition() { - const groupByType = RocketChat.getUserPreference(Meteor.userId(), 'sidebarGroupByType'); - return groupByType && RocketChat.authz.hasAtLeastOnePermission(['view-d-room', 'view-joined-room']); + const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); + return groupByType && hasAtLeastOnePermission(['view-d-room', 'view-joined-room']); } getUserStatus(roomId) { - const subscription = RocketChat.models.Subscriptions.findOne({ rid: roomId }); + const subscription = Subscriptions.findOne({ rid: roomId }); if (subscription == null) { return; } @@ -95,7 +99,7 @@ export class DirectMessageRoomType extends RoomTypeConfig { case RoomSettingsEnum.JOIN_CODE: return false; case RoomSettingsEnum.E2E: - return RocketChat.settings.get('E2E_Enable') === true; + return settings.get('E2E_Enable') === true; default: return true; } @@ -133,7 +137,7 @@ export class DirectMessageRoomType extends RoomTypeConfig { return {}; } - const title = RocketChat.settings.get('UI_Use_Real_Name') ? user.name : `@${ user.username }`; + const title = settings.get('UI_Use_Real_Name') ? user.name : `@${ user.username }`; const text = notificationMessage; return { title, text }; diff --git a/packages/rocketchat-lib/lib/roomTypes/favorite.js b/packages/rocketchat-lib/lib/roomTypes/favorite.js index af598aca06c6..4aac1fd098b0 100644 --- a/packages/rocketchat-lib/lib/roomTypes/favorite.js +++ b/packages/rocketchat-lib/lib/roomTypes/favorite.js @@ -1,4 +1,6 @@ import { Meteor } from 'meteor/meteor'; +import { settings } from 'meteor/rocketchat:settings'; +import { getUserPreference } from 'meteor/rocketchat:utils'; import { RoomTypeConfig } from '../RoomTypeConfig'; export class FavoriteRoomType extends RoomTypeConfig { @@ -12,6 +14,6 @@ export class FavoriteRoomType extends RoomTypeConfig { }); } condition() { - return RocketChat.settings.get('Favorite_Rooms') && RocketChat.getUserPreference(Meteor.userId(), 'sidebarShowFavorites'); + return settings.get('Favorite_Rooms') && getUserPreference(Meteor.userId(), 'sidebarShowFavorites'); } } diff --git a/packages/rocketchat-lib/lib/roomTypes/private.js b/packages/rocketchat-lib/lib/roomTypes/private.js index 9a2eabc7c4ea..3618072f8729 100644 --- a/packages/rocketchat-lib/lib/roomTypes/private.js +++ b/packages/rocketchat-lib/lib/roomTypes/private.js @@ -1,6 +1,10 @@ import { Meteor } from 'meteor/meteor'; -import { RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig, UiTextContext } from '../RoomTypeConfig'; import { ChatRoom } from 'meteor/rocketchat:models'; +import { openRoom } from 'meteor/rocketchat:ui-utils'; +import { settings } from 'meteor/rocketchat:settings'; +import { hasAtLeastOnePermission, hasPermission } from 'meteor/rocketchat:authorization'; +import { getUserPreference } from 'meteor/rocketchat:utils'; +import { RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig, UiTextContext } from '../RoomTypeConfig'; export class PrivateRoomRoute extends RoomTypeRouteConfig { constructor() { @@ -36,7 +40,7 @@ export class PrivateRoomType extends RoomTypeConfig { } roomName(roomData) { - if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { + if (settings.get('UI_Allow_room_names_with_special_chars')) { return roomData.fname || roomData.name; } @@ -44,8 +48,8 @@ export class PrivateRoomType extends RoomTypeConfig { } condition() { - const groupByType = RocketChat.getUserPreference(Meteor.userId(), 'sidebarGroupByType'); - return groupByType && RocketChat.authz.hasPermission('view-p-room'); + const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); + return groupByType && hasPermission('view-p-room'); } isGroupChat() { @@ -53,7 +57,7 @@ export class PrivateRoomType extends RoomTypeConfig { } canAddUser(room) { - return RocketChat.authz.hasAtLeastOnePermission(['add-user-to-any-p-room', 'add-user-to-joined-room'], room._id); + return hasAtLeastOnePermission(['add-user-to-any-p-room', 'add-user-to-joined-room'], room._id); } allowRoomSettingChange(room, setting) { @@ -68,7 +72,7 @@ export class PrivateRoomType extends RoomTypeConfig { return !room.broadcast && room.ro; case RoomSettingsEnum.SYSTEM_MESSAGES: case RoomSettingsEnum.E2E: - return RocketChat.settings.get('E2E_Enable') === true; + return settings.get('E2E_Enable') === true; default: return true; } diff --git a/packages/rocketchat-lib/lib/roomTypes/public.js b/packages/rocketchat-lib/lib/roomTypes/public.js index 6ccc7cd1176a..c69a8086674c 100644 --- a/packages/rocketchat-lib/lib/roomTypes/public.js +++ b/packages/rocketchat-lib/lib/roomTypes/public.js @@ -1,6 +1,10 @@ import { Meteor } from 'meteor/meteor'; -import { RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, UiTextContext } from '../RoomTypeConfig'; +import { openRoom } from 'meteor/rocketchat:ui-utils'; import { ChatRoom } from 'meteor/rocketchat:models'; +import { settings } from 'meteor/rocketchat:settings'; +import { hasAtLeastOnePermission } from 'meteor/rocketchat:authorization'; +import { getUserPreference } from 'meteor/rocketchat:utils'; +import { RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, UiTextContext } from '../RoomTypeConfig'; export class PublicRoomRoute extends RoomTypeRouteConfig { constructor() { @@ -35,15 +39,15 @@ export class PublicRoomType extends RoomTypeConfig { } roomName(roomData) { - if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) { + if (settings.get('UI_Allow_room_names_with_special_chars')) { return roomData.fname || roomData.name; } return roomData.name; } condition() { - const groupByType = RocketChat.getUserPreference(Meteor.userId(), 'sidebarGroupByType'); - return groupByType && (RocketChat.authz.hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || RocketChat.settings.get('Accounts_AllowAnonymousRead') === true); + const groupByType = getUserPreference(Meteor.userId(), 'sidebarGroupByType'); + return groupByType && (hasAtLeastOnePermission(['view-c-room', 'view-joined-room']) || settings.get('Accounts_AllowAnonymousRead') === true); } showJoinLink(roomId) { @@ -59,7 +63,7 @@ export class PublicRoomType extends RoomTypeConfig { } canAddUser(room) { - return RocketChat.authz.hasAtLeastOnePermission(['add-user-to-any-c-room', 'add-user-to-joined-room'], room._id); + return hasAtLeastOnePermission(['add-user-to-any-c-room', 'add-user-to-joined-room'], room._id); } enableMembersListProfile() { diff --git a/packages/rocketchat-lib/lib/roomTypes/unread.js b/packages/rocketchat-lib/lib/roomTypes/unread.js index 64926533670f..30c287bbe0b9 100644 --- a/packages/rocketchat-lib/lib/roomTypes/unread.js +++ b/packages/rocketchat-lib/lib/roomTypes/unread.js @@ -1,4 +1,5 @@ import { Meteor } from 'meteor/meteor'; +import { getUserPreference } from 'meteor/rocketchat:utils'; import { RoomTypeConfig } from '../RoomTypeConfig'; export class UnreadRoomType extends RoomTypeConfig { @@ -13,6 +14,6 @@ export class UnreadRoomType extends RoomTypeConfig { } condition() { - return RocketChat.getUserPreference(Meteor.userId(), 'sidebarShowUnread'); + return getUserPreference(Meteor.userId(), 'sidebarShowUnread'); } } diff --git a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js index 7d6aa29034a5..4a3ac0c967c2 100644 --- a/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js +++ b/packages/rocketchat-lib/lib/startup/settingsOnLoadSiteUrl.js @@ -1,7 +1,10 @@ import { Meteor } from 'meteor/meteor'; import { WebAppInternals } from 'meteor/webapp'; +import { settings } from 'meteor/rocketchat:settings'; -RocketChat.settings.get('Site_Url', function(key, value) { +export let hostname; + +settings.get('Site_Url', function(key, value) { if (value == null || value.trim() === '') { return; } @@ -18,7 +21,7 @@ RocketChat.settings.get('Site_Url', function(key, value) { Meteor.absoluteUrl.defaultOptions.rootUrl = value; } if (Meteor.isServer) { - RocketChat.hostname = host.replace(/^https?:\/\//, ''); + hostname = host.replace(/^https?:\/\//, ''); process.env.MOBILE_ROOT_URL = host; process.env.MOBILE_DDP_URL = host; if (typeof WebAppInternals !== 'undefined' && WebAppInternals.generateBoilerplate) { diff --git a/packages/rocketchat-lib/server/lib/index.js b/packages/rocketchat-lib/server/lib/index.js index 7d9a272a1a8d..5cf680b6e8b9 100644 --- a/packages/rocketchat-lib/server/lib/index.js +++ b/packages/rocketchat-lib/server/lib/index.js @@ -8,6 +8,7 @@ import { RoomSettingsEnum, RoomTypeConfig, RoomTypeRouteConfig } from '../../lib/RoomTypeConfig'; import { sendNotification } from './sendNotificationsOnMessage.js'; +export { hostname } from '../../lib/startup/settingsOnLoadSiteUrl'; export { RoomSettingsEnum, diff --git a/packages/rocketchat-ui-utils/client/index.js b/packages/rocketchat-ui-utils/client/index.js index add1d9559fbe..c440cbd9091c 100644 --- a/packages/rocketchat-ui-utils/client/index.js +++ b/packages/rocketchat-ui-utils/client/index.js @@ -23,3 +23,5 @@ export { popout } from './lib/popout'; export { messageProperties } from '../lib/MessageProperties'; export { MessageTypes } from '../lib/MessageTypes'; export { alerts } from './lib/alerts'; +export { Message } from '../lib/Message'; +export { currentTracker, openRoom } from './lib/openRoom'; diff --git a/packages/rocketchat-ui-utils/client/lib/openRoom.js b/packages/rocketchat-ui-utils/client/lib/openRoom.js new file mode 100644 index 000000000000..f139295111ab --- /dev/null +++ b/packages/rocketchat-ui-utils/client/lib/openRoom.js @@ -0,0 +1,102 @@ +import { Meteor } from 'meteor/meteor'; +import { Tracker } from 'meteor/tracker'; +import { FlowRouter } from 'meteor/kadira:flow-router'; +import { BlazeLayout } from 'meteor/kadira:blaze-layout'; +import { Session } from 'meteor/session'; +import { RoomManager, fireGlobalEvent, readMessage, RoomHistoryManager, Layout } from '..'; +import { ChatSubscription, Rooms } from 'meteor/rocketchat:models'; +import { settings } from 'meteor/rocketchat:settings'; +import { callbacks } from 'meteor/rocketchat:callbacks'; +import { roomTypes, handleError } from 'meteor/rocketchat:utils'; +import _ from 'underscore'; + +export let currentTracker = undefined; + +export const openRoom = function(type, name) { + Session.set('openedRoom', null); + + return Meteor.defer(() => + currentTracker = Tracker.autorun(function(c) { + const user = Meteor.user(); + if ((user && user.username == null) || (user == null && settings.get('Accounts_AllowAnonymousRead') === false)) { + BlazeLayout.render('main'); + return; + } + + if (RoomManager.open(type + name).ready() !== true) { + BlazeLayout.render('main', { modal: Layout.isEmbedded(), center: 'loading' }); + return; + } + if (currentTracker) { + currentTracker = undefined; + } + c.stop(); + + const room = roomTypes.findRoom(type, name, user); + if (room == null) { + if (type === 'd') { + Meteor.call('createDirectMessage', name, function(error) { + if (!error) { + RoomManager.close(type + name); + return openRoom('d', name); + } else { + Session.set('roomNotFound', { type, name, error }); + BlazeLayout.render('main', { center: 'roomNotFound' }); + return; + } + }); + } else { + Meteor.call('getRoomByTypeAndName', type, name, function(error, record) { + if (error) { + Session.set('roomNotFound', { type, name, error }); + return BlazeLayout.render('main', { center: 'roomNotFound' }); + } else { + Rooms.upsert({ _id: record._id }, _.omit(record, '_id')); + RoomManager.close(type + name); + return openRoom(type, name); + } + }); + } + return; + } + + const mainNode = document.querySelector('.main-content'); + if (mainNode) { + for (const child of Array.from(mainNode.children)) { + if (child) { mainNode.removeChild(child); } + } + const roomDom = RoomManager.getDomOfRoom(type + name, room._id); + mainNode.appendChild(roomDom); + if (roomDom.classList.contains('room-container')) { + roomDom.querySelector('.messages-box > .wrapper').scrollTop = roomDom.oldScrollTop; + } + } + + Session.set('openedRoom', room._id); + RoomManager.openedRoom = room._id; + + fireGlobalEvent('room-opened', _.omit(room, 'usernames')); + + Session.set('editRoomTitle', false); + RoomManager.updateMentionsMarksOfRoom(type + name); + Meteor.setTimeout(() => readMessage.readNow(), 2000); + // KonchatNotification.removeRoomNotification(params._id) + // update user's room subscription + const sub = ChatSubscription.findOne({ rid: room._id }); + if (sub && sub.open === false) { + Meteor.call('openRoom', room._id, function(err) { + if (err) { + return handleError(err); + } + }); + } + + if (FlowRouter.getQueryParam('msg')) { + const msg = { _id: FlowRouter.getQueryParam('msg'), rid: room._id }; + RoomHistoryManager.getSurroundingMessages(msg); + } + + return callbacks.run('enter-room', sub); + }) + ); +}; diff --git a/packages/rocketchat-ui-utils/lib/Message.js b/packages/rocketchat-ui-utils/lib/Message.js new file mode 100644 index 000000000000..6d595dc37804 --- /dev/null +++ b/packages/rocketchat-ui-utils/lib/Message.js @@ -0,0 +1,34 @@ +import { TAPi18n } from 'meteor/tap:i18n'; +import { settings } from 'meteor/rocketchat:settings'; +import s from 'underscore.string'; +import { MessageTypes } from './MessageTypes'; + +export const Message = { + parse(msg, language) { + const messageType = MessageTypes.getType(msg); + if (messageType) { + if (messageType.render) { + return messageType.render(msg); + } else if (messageType.template) { + // Render message + return; + } else if (messageType.message) { + if (!language && typeof localStorage !== 'undefined') { + language = localStorage.getItem('userLanguage'); + } + const data = (typeof messageType.data === 'function' && messageType.data(msg)) || {}; + return TAPi18n.__(messageType.message, data, language); + } + } + if (msg.u && msg.u.username === settings.get('Chatops_Username')) { + msg.html = msg.msg; + return msg.html; + } + msg.html = msg.msg; + if (s.trim(msg.html) !== '') { + msg.html = s.escapeHTML(msg.html); + } + msg.html = msg.html.replace(/\n/gm, '
'); + return msg.html; + }, +}; diff --git a/packages/rocketchat-ui-utils/package.js b/packages/rocketchat-ui-utils/package.js index aacd2e789d84..da1129cc1063 100644 --- a/packages/rocketchat-ui-utils/package.js +++ b/packages/rocketchat-ui-utils/package.js @@ -10,10 +10,12 @@ Package.onUse(function(api) { api.use([ 'ecmascript', 'http', + 'tap:i18n', 'templating', 'kadira:flow-router', 'kadira:blaze-layout', 'rocketchat:utils', + 'rocketchat:settings', 'rocketchat:promises', 'rocketchat:notifications', 'rocketchat:authorization', diff --git a/packages/rocketchat-ui-utils/server/index.js b/packages/rocketchat-ui-utils/server/index.js index d10c21758175..35066a1ea46d 100644 --- a/packages/rocketchat-ui-utils/server/index.js +++ b/packages/rocketchat-ui-utils/server/index.js @@ -1,2 +1,3 @@ export { messageProperties } from '../lib/MessageProperties'; export { MessageTypes } from '../lib/MessageTypes'; +export { Message } from '../lib/Message'; diff --git a/packages/rocketchat-utils/client/index.js b/packages/rocketchat-utils/client/index.js index 97d18ad672b7..3fc66523a403 100644 --- a/packages/rocketchat-utils/client/index.js +++ b/packages/rocketchat-utils/client/index.js @@ -13,3 +13,7 @@ export { getAvatarUrlFromUsername } from '../lib/getAvatarUrlFromUsername'; export { slashCommands } from '../lib/slashCommand'; export { getUserNotificationPreference } from '../lib/getUserNotificationPreference'; export { applyCustomTranslations } from './lib/CustomTranslations'; +export { getAvatarColor } from '../lib/getAvatarColor'; +export { getURL } from '../lib/getURL'; +export { getValidRoomName } from '../lib/getValidRoomName'; +export { placeholders } from '../lib/placeholders'; diff --git a/packages/rocketchat-utils/lib/getAvatarColor.js b/packages/rocketchat-utils/lib/getAvatarColor.js new file mode 100644 index 000000000000..867d9982e863 --- /dev/null +++ b/packages/rocketchat-utils/lib/getAvatarColor.js @@ -0,0 +1,3 @@ +const colors = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39', '#FFC107', '#FF9800', '#FF5722', '#795548', '#9E9E9E', '#607D8B']; + +export const getAvatarColor = (name) => colors[name.length % colors.length]; diff --git a/packages/rocketchat-utils/lib/getURL.js b/packages/rocketchat-utils/lib/getURL.js new file mode 100644 index 000000000000..e314a6b58c80 --- /dev/null +++ b/packages/rocketchat-utils/lib/getURL.js @@ -0,0 +1,22 @@ +import { Meteor } from 'meteor/meteor'; +import { settings } from 'meteor/rocketchat:settings'; +import s from 'underscore.string'; + +export const getURL = (path, { cdn = true, full = false } = {}) => { + const cdnPrefix = s.rtrim(s.trim(settings.get('CDN_PREFIX') || ''), '/'); + const pathPrefix = s.rtrim(s.trim(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ''), '/'); + + let basePath; + + const finalPath = s.ltrim(s.trim(path), '/'); + + if (cdn && cdnPrefix !== '') { + basePath = cdnPrefix + pathPrefix; + } else if (full) { + return Meteor.absoluteUrl(finalPath); + } else { + basePath = pathPrefix; + } + + return `${ basePath }/${ finalPath }`; +}; diff --git a/packages/rocketchat-utils/lib/getValidRoomName.js b/packages/rocketchat-utils/lib/getValidRoomName.js new file mode 100644 index 000000000000..92306dc00983 --- /dev/null +++ b/packages/rocketchat-utils/lib/getValidRoomName.js @@ -0,0 +1,51 @@ +import { Meteor } from 'meteor/meteor'; +import { settings } from 'meteor/rocketchat:settings'; +import { Rooms } from 'meteor/rocketchat:models'; +import s from 'underscore.string'; + +export const getValidRoomName = (displayName, rid = '') => { + let slugifiedName = displayName; + + if (settings.get('UI_Allow_room_names_with_special_chars')) { + const room = Rooms.findOneByDisplayName(displayName); + if (room && room._id !== rid) { + if (room.archived) { + throw new Meteor.Error('error-archived-duplicate-name', `There's an archived channel with name ${ displayName }`, { function: 'RocketChat.getValidRoomName', channel_name: displayName }); + } else { + throw new Meteor.Error('error-duplicate-channel-name', `A channel with name '${ displayName }' exists`, { function: 'RocketChat.getValidRoomName', channel_name: displayName }); + } + } + slugifiedName = s.slugify(displayName); + } + + let nameValidation; + try { + nameValidation = new RegExp(`^${ settings.get('UTF8_Names_Validation') }$`); + } catch (error) { + nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$'); + } + if (!nameValidation.test(slugifiedName)) { + throw new Meteor.Error('error-invalid-room-name', `${ slugifiedName } is not a valid room name.`, { + function: 'RocketChat.getValidRoomName', + channel_name: slugifiedName, + }); + } + + const room = Rooms.findOneByName(slugifiedName); + if (room && room._id !== rid) { + if (settings.get('UI_Allow_room_names_with_special_chars')) { + let tmpName = slugifiedName; + let next = 0; + while (Rooms.findOneByNameAndNotId(tmpName, rid)) { + tmpName = `${ slugifiedName }-${ ++next }`; + } + slugifiedName = tmpName; + } else if (room.archived) { + throw new Meteor.Error('error-archived-duplicate-name', `There's an archived channel with name ${ slugifiedName }`, { function: 'RocketChat.getValidRoomName', channel_name: slugifiedName }); + } else { + throw new Meteor.Error('error-duplicate-channel-name', `A channel with name '${ slugifiedName }' exists`, { function: 'RocketChat.getValidRoomName', channel_name: slugifiedName }); + } + } + + return slugifiedName; +}; diff --git a/packages/rocketchat-utils/lib/placeholders.js b/packages/rocketchat-utils/lib/placeholders.js new file mode 100644 index 000000000000..274005672aa0 --- /dev/null +++ b/packages/rocketchat-utils/lib/placeholders.js @@ -0,0 +1,32 @@ +import { settings } from 'meteor/rocketchat:settings'; +import s from 'underscore.string'; + +export const placeholders = { + replace: (str, data) => { + if (!str) { + return ''; + } + + str = str.replace(/\[Site_Name\]/g, settings.get('Site_Name') || ''); + str = str.replace(/\[Site_URL\]/g, settings.get('Site_Url') || ''); + + if (data) { + str = str.replace(/\[name\]/g, data.name || ''); + str = str.replace(/\[fname\]/g, s.strLeft(data.name, ' ') || ''); + str = str.replace(/\[lname\]/g, s.strRightBack(data.name, ' ') || ''); + str = str.replace(/\[email\]/g, data.email || ''); + str = str.replace(/\[password\]/g, data.password || ''); + str = str.replace(/\[reason\]/g, data.reason || ''); + str = str.replace(/\[User\]/g, data.user || ''); + str = str.replace(/\[Room\]/g, data.room || ''); + + if (data.unsubscribe) { + str = str.replace(/\[unsubscribe\]/g, data.unsubscribe); + } + } + + str = str.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '
' + '$2'); + + return str; + }, +}; diff --git a/packages/rocketchat-utils/server/index.js b/packages/rocketchat-utils/server/index.js index e0585eebb4b4..48af9bdf8458 100644 --- a/packages/rocketchat-utils/server/index.js +++ b/packages/rocketchat-utils/server/index.js @@ -1,32 +1,16 @@ -import { t, isRtl } from '../lib/tapi18n'; -import { getDefaultSubscriptionPref } from '../lib/getDefaultSubscriptionPref'; -import { Info } from '../rocketchat.info'; -import { getUserPreference } from '../lib/getUserPreference'; -import { fileUploadMediaWhiteList, fileUploadIsValidContentType } from '../lib/fileUploadRestrictions'; -import { roomTypes } from './lib/roomTypes'; -import { RoomTypeRouteConfig, RoomTypeConfig, RoomSettingsEnum, UiTextContext } from '../lib/RoomTypeConfig'; -import { RoomTypesCommon } from '../lib/RoomTypesCommon'; -import { isDocker } from './functions/isDocker'; -import { getAvatarUrlFromUsername } from '../lib/getAvatarUrlFromUsername'; -import { slashCommands } from '../lib/slashCommand'; -import { getUserNotificationPreference } from '../lib/getUserNotificationPreference'; - -export { - t, - isRtl, - getDefaultSubscriptionPref, - Info, - getUserPreference, - fileUploadIsValidContentType, - fileUploadMediaWhiteList, - roomTypes, - RoomTypeRouteConfig, - RoomTypesCommon, - RoomTypeConfig, - RoomSettingsEnum, - UiTextContext, - isDocker, - getAvatarUrlFromUsername, - slashCommands, - getUserNotificationPreference, -}; +export { t, isRtl } from '../lib/tapi18n'; +export { getDefaultSubscriptionPref } from '../lib/getDefaultSubscriptionPref'; +export { Info } from '../rocketchat.info'; +export { getUserPreference } from '../lib/getUserPreference'; +export { fileUploadMediaWhiteList, fileUploadIsValidContentType } from '../lib/fileUploadRestrictions'; +export { roomTypes } from './lib/roomTypes'; +export { RoomTypeRouteConfig, RoomTypeConfig, RoomSettingsEnum, UiTextContext } from '../lib/RoomTypeConfig'; +export { RoomTypesCommon } from '../lib/RoomTypesCommon'; +export { isDocker } from './functions/isDocker'; +export { getAvatarUrlFromUsername } from '../lib/getAvatarUrlFromUsername'; +export { slashCommands } from '../lib/slashCommand'; +export { getUserNotificationPreference } from '../lib/getUserNotificationPreference'; +export { getAvatarColor } from '../lib/getAvatarColor'; +export { getURL } from '../lib/getURL'; +export { getValidRoomName } from '../lib/getValidRoomName'; +export { placeholders } from '../lib/placeholders';