Пример #1
0
Meteor.publish('livechat:managers', function() {
	if (!this.userId) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:managers' }));
	}

	if (!RocketChat.authz.hasPermission(this.userId, 'view-livechat-rooms')) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:managers' }));
	}

	const self = this;

	const handle = RocketChat.authz.getUsersInRole('livechat-manager').observeChanges({
		added(id, fields) {
			self.added('managerUsers', id, fields);
		},
		changed(id, fields) {
			self.changed('managerUsers', id, fields);
		},
		removed(id) {
			self.removed('managerUsers', id);
		},
	});

	self.ready();

	self.onStop(function() {
		handle.stop();
	});
});
	this.autorun(() => {
		const id = this.data && this.data.params && this.data.params().id;

		if (id) {
			const sub = this.subscribe('integrations');
			if (sub.ready()) {
				let intRecord;

				if (RocketChat.authz.hasAllPermission('manage-integrations')) {
					intRecord = ChatIntegrations.findOne({ _id: id });
				} else if (RocketChat.authz.hasAllPermission('manage-own-integrations')) {
					intRecord = ChatIntegrations.findOne({ _id: id, '_createdBy._id': Meteor.userId() });
				}

				if (!intRecord) {
					toastr.error(TAPi18n.__('No_integration_found'));
					FlowRouter.go('admin-integrations');
				}

				const historySub = this.subscribe('integrationHistory', intRecord._id, this.limit.get());
				if (historySub.ready()) {
					if (ChatIntegrationHistory.find().count() > this.limit.get()) {
						this.hasMore.set(true);
					}
				}
			}
		} else {
			toastr.error(TAPi18n.__('No_integration_found'));
			FlowRouter.go('admin-integrations');
		}
	});
Пример #3
0
function canShowAddUsersButton(rid) {
	const canAddToChannel = RocketChat.authz.hasAllPermission(
		'add-user-to-any-c-room', rid
	);
	const canAddToGroup = RocketChat.authz.hasAllPermission(
		'add-user-to-any-p-room', rid
	);
	const canAddToJoinedRoom = RocketChat.authz.hasAllPermission(
		'add-user-to-joined-room', rid
	);
	if (
		!canAddToJoinedRoom &&
		!canAddToChannel &&
		Template.instance().tabBar.currentGroup() === 'channel'
	) {
		return false;
	}
	if (
		!canAddToJoinedRoom &&
		!canAddToGroup &&
		Template.instance().tabBar.currentGroup() === 'group'
	) {
		return false;
	}
	return true;
}
Пример #4
0
Meteor.publish('integrations', function _integrationPublication() {
	if (!this.userId) {
		return this.ready();
	}

	if (RocketChat.authz.hasPermission(this.userId, 'manage-integrations')) {
		return RocketChat.models.Integrations.find();
	} else if (RocketChat.authz.hasPermission(this.userId, 'manage-own-integrations')) {
		return RocketChat.models.Integrations.find({ '_createdBy._id': this.userId });
	} else {
		throw new Meteor.Error('not-authorized');
	}
});
Пример #5
0
const fetchRoomsFromServer = (filterText, records, cb, rid) => {
	if (!RocketChat.authz.hasAllPermission('view-outside-room')) {
		return cb && cb([]);
	}

	return Meteor.call('spotlight', filterText, null, { rooms: true }, rid, (error, results) => {
		if (error) {
			return console.error(error);
		}

		const { rooms } = results;

		if (!rooms || rooms.length <= 0) {
			return;
		}

		rooms.slice(0, 5).forEach((room) => {
			if (records.length < 5) {
				records.push(room);
			}
		});

		return cb && cb(records);
	});
};
Пример #6
0
				endpoints[method].action = function _internalRouteActionHandler() {
					const rocketchatRestApiEnd = RocketChat.metrics.rocketchatRestApi.startTimer({
						method,
						version,
						user_agent: this.request.headers['user-agent'],
						entrypoint: route,
					});

					logger.debug(`${ this.request.method.toUpperCase() }: ${ this.request.url }`);
					const requestIp = this.request.headers['x-forwarded-for'] || this.request.connection.remoteAddress || this.request.socket.remoteAddress || this.request.connection.socket.remoteAddress;
					const objectForRateLimitMatch = {
						IPAddr: requestIp,
						route: `${ this.request.route }${ this.request.method.toLowerCase() }`,
					};
					let result;
					try {
						const shouldVerifyRateLimit = rateLimiterDictionary.hasOwnProperty(objectForRateLimitMatch.route)
							&& (!this.userId || !RocketChat.authz.hasPermission(this.userId, 'api-bypass-rate-limit'))
							&& ((process.env.NODE_ENV === 'development' && RocketChat.settings.get('API_Enable_Rate_Limiter_Dev') === true) || process.env.NODE_ENV !== 'development');
						if (shouldVerifyRateLimit) {
							rateLimiterDictionary[objectForRateLimitMatch.route].rateLimiter.increment(objectForRateLimitMatch);
							const attemptResult = rateLimiterDictionary[objectForRateLimitMatch.route].rateLimiter.check(objectForRateLimitMatch);
							const timeToResetAttempsInSeconds = Math.ceil(attemptResult.timeToReset / 1000);
							this.response.setHeader('X-RateLimit-Limit', rateLimiterDictionary[objectForRateLimitMatch.route].options.numRequestsAllowed);
							this.response.setHeader('X-RateLimit-Remaining', attemptResult.numInvocationsLeft);
							this.response.setHeader('X-RateLimit-Reset', new Date().getTime() + attemptResult.timeToReset);
							if (!attemptResult.allowed) {
								throw new Meteor.Error('error-too-many-requests', `Error, too many requests. Please slow down. You must wait ${ timeToResetAttempsInSeconds } seconds before trying this endpoint again.`, {
									timeToReset: attemptResult.timeToReset,
									seconds: timeToResetAttempsInSeconds,
								});
							}
						}

						if (shouldVerifyPermissions && (!this.userId || !hasAllPermission(this.userId, options.permissionsRequired))) {
							throw new Meteor.Error('error-unauthorized', 'User does not have the permissions required for this action', {
								permissions: options.permissionsRequired,
							});
						}

						result = originalAction.apply(this);
					} catch (e) {
						logger.debug(`${ method } ${ route } threw an error:`, e.stack);

						const apiMethod = {
							'error-too-many-requests': 'tooManyRequests',
							'error-unauthorized': 'unauthorized',
						}[e.error] || 'failure';

						result = RocketChat.API.v1[apiMethod](e.message, e.error);
					}

					result = result || RocketChat.API.v1.success();

					rocketchatRestApiEnd({
						status: result.statusCode,
					});

					return result;
				};
Пример #7
0
Meteor.publish('oauthApps', function() {
	if (!this.userId) {
		return this.ready();
	}
	if (!RocketChat.authz.hasPermission(this.userId, 'manage-oauth-apps')) {
		this.error(Meteor.Error('error-not-allowed', 'Not allowed', { publish: 'oauthApps' }));
	}
	return RocketChat.models.OAuthApps.find();
});
Пример #8
0
				}).filter((command) => {
					const isMatch = command._id.indexOf(filter) > -1;

					if (!isMatch) {
						return false;
					}

					if (!command.permission) {
						return true;
					}

					return RocketChat.authz.hasAtLeastOnePermission(command.permission, Session.get('openedRoom'));
				}).sort((a, b) => a._id > b._id).slice(0, 11);
Пример #9
0
Meteor.publish('livechat:appearance', function() {
	if (!this.userId) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:appearance' }));
	}

	if (!RocketChat.authz.hasPermission(this.userId, 'view-livechat-manager')) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:appearance' }));
	}

	const query = {
		_id: {
			$in: [
				'Livechat_title',
				'Livechat_title_color',
				'Livechat_show_agent_email',
				'Livechat_display_offline_form',
				'Livechat_offline_form_unavailable',
				'Livechat_offline_message',
				'Livechat_offline_success_message',
				'Livechat_offline_title',
				'Livechat_offline_title_color',
				'Livechat_offline_email',
				'Livechat_conversation_finished_message',
				'Livechat_registration_form',
				'Livechat_name_field_registration_form',
				'Livechat_email_field_registration_form',
				'Livechat_registration_form_message',
			],
		},
	};

	const self = this;

	const handle = RocketChat.models.Settings.find(query).observeChanges({
		added(id, fields) {
			self.added('livechatAppearance', id, fields);
		},
		changed(id, fields) {
			self.changed('livechatAppearance', id, fields);
		},
		removed(id) {
			self.removed('livechatAppearance', id);
		},
	});

	this.ready();

	this.onStop(() => {
		handle.stop();
	});
});
Пример #10
0
						file.on('end', Meteor.bindEnvironment(() => {
							const sentTheUserByFormData = fields.userId || fields.username;
							if (sentTheUserByFormData) {
								user = getUserFromFormData(fields);
								if (!user) {
									return callback(new Meteor.Error('error-invalid-user', 'The optional "userId" or "username" param provided does not match any users'));
								}
								if (!RocketChat.authz.hasPermission(this.userId, 'edit-other-user-info')) {
									return callback(new Meteor.Error('error-not-allowed', 'Not allowed'));
								}
							}
							RocketChat.setUserAvatar(user, Buffer.concat(imageData), mimetype, 'rest');
							callback();
						}));
Пример #11
0
Meteor.startup(() => {
	RocketChat.roomTypes.setRoomFind('l', (_id) => RocketChat.models.Rooms.findLivechatById(_id).fetch());

	RocketChat.authz.addRoomAccessValidator(function(room, user) {
		return room && room.t === 'l' && user && RocketChat.authz.hasPermission(user._id, 'view-livechat-rooms');
	});

	RocketChat.authz.addRoomAccessValidator(function(room, user, extraData) {
		if (!room && extraData && extraData.rid) {
			room = RocketChat.models.Rooms.findOneById(extraData.rid);
		}
		return room && room.t === 'l' && extraData && extraData.visitorToken && room.v && room.v.token === extraData.visitorToken;
	});

	RocketChat.callbacks.add('beforeLeaveRoom', function(user, room) {
		if (room.t !== 'l') {
			return user;
		}
		throw new Meteor.Error(TAPi18n.__('You_cant_leave_a_livechat_room_Please_use_the_close_button', {
			lng: user.language || RocketChat.settings.get('Language') || 'en',
		}));
	}, RocketChat.callbacks.priority.LOW, 'cant-leave-room');
});
Пример #12
0
Meteor.publish('livechat:customFields', function(_id) {
	if (!this.userId) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:customFields' }));
	}

	if (!RocketChat.authz.hasPermission(this.userId, 'view-l-room')) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:customFields' }));
	}

	if (s.trim(_id)) {
		return RocketChat.models.LivechatCustomField.find({ _id });
	}

	return RocketChat.models.LivechatCustomField.find();

});
Пример #13
0
function createChannelValidator(params) {
	if (!RocketChat.authz.hasPermission(params.user.value, 'create-c')) {
		throw new Error('unauthorized');
	}

	if (!params.name || !params.name.value) {
		throw new Error(`Param "${ params.name.key }" is required`);
	}

	if (params.members && params.members.value && !_.isArray(params.members.value)) {
		throw new Error(`Param "${ params.members.key }" must be an array if provided`);
	}

	if (params.customFields && params.customFields.value && !(typeof params.customFields.value === 'object')) {
		throw new Error(`Param "${ params.customFields.key }" must be an object if provided`);
	}
}
Пример #14
0
Meteor.publish('adminRooms', function(filter, types, limit) {
	if (!this.userId) {
		return this.ready();
	}
	if (RocketChat.authz.hasPermission(this.userId, 'view-room-administration') !== true) {
		return this.ready();
	}
	if (!_.isArray(types)) {
		types = [];
	}

	const options = {
		fields: {
			name: 1,
			t: 1,
			cl: 1,
			u: 1,
			usernames: 1,
			muted: 1,
			ro: 1,
			default: 1,
			topic: 1,
			msgs: 1,
			archived: 1,
			tokenpass: 1,
		},
		limit,
		sort: {
			default: -1,
			name: 1,
		},
	};

	filter = s.trim(filter);
	if (filter && types.length) {
		// CACHE: can we stop using publications here?
		return RocketChat.models.Rooms.findByNameContainingAndTypes(filter, types, options);
	} else if (types.length) {
		// CACHE: can we stop using publications here?
		return RocketChat.models.Rooms.findByTypes(types, options);
	} else {
		// CACHE: can we stop using publications here?
		return RocketChat.models.Rooms.findByNameContaining(filter, options);
	}
});
Пример #15
0
Meteor.publish('livechat:monitoring', function(date) {
	if (!this.userId) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:monitoring' }));
	}

	if (!RocketChat.authz.hasPermission(this.userId, 'view-livechat-manager')) {
		return this.error(new Meteor.Error('error-not-authorized', 'Not authorized', { publish: 'livechat:monitoring' }));
	}

	date = {
		gte: new Date(date.gte),
		lt: new Date(date.lt),
	};

	check(date.gte, Date);
	check(date.lt, Date);

	const self = this;

	const handle = RocketChat.models.Rooms.getAnalyticsMetricsBetweenDate('l', date).observeChanges({
		added(id, fields) {
			self.added('livechatMonitoring', id, fields);
		},
		changed(id, fields) {
			self.changed('livechatMonitoring', id, fields);
		},
		removed(id) {
			self.removed('livechatMonitoring', id);
		},
	});

	self.ready();

	self.onStop(function() {
		handle.stop();
	});
});
Пример #16
0
import { Meteor } from 'meteor/meteor';
import { RocketChat } from 'meteor/rocketchat:lib';

Meteor.methods({
	getStatistics(refresh) {
		if (!Meteor.userId()) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getStatistics' });
		}

		if (RocketChat.authz.hasPermission(Meteor.userId(), 'view-statistics') !== true) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getStatistics' });
		}

		if (refresh) {
			return RocketChat.statistics.save();
		} else {
			return RocketChat.models.Statistics.findLast();
		}
	},
});
Пример #17
0
	RocketChat.authz.addRoomAccessValidator(function(room, user) {
		return room && room.t === 'l' && user && RocketChat.authz.hasPermission(user._id, 'view-livechat-rooms');
	});
Пример #18
0
Template.channelSettingsEditing.onCreated(function() {
	const room = this.room = ChatRoom.findOne(this.data && this.data.rid);
	this.settings = {
		name: {
			type: 'text',
			label: 'Name',
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.NAME);
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			getValue() {
				if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
					return room.fname || room.name;
				}

				return room.name;
			},
			save(value) {
				let nameValidation;

				if (!RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
					try {
						nameValidation = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`);
					} catch (error1) {
						nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
					}

					if (!nameValidation.test(value)) {
						return Promise.reject(toastr.error(t('error-invalid-room-name', {
							room_name: {
								name: value,
							},
						})));
					}
				}
				return call('saveRoomSettings', room._id, RoomSettingsEnum.NAME, value).then(function() {
					RocketChat.callbacks.run('roomNameChanged', {
						_id: room._id,
						name: value,
					});

					return toastr.success(t('Room_name_changed_successfully'));
				});
			},
		},
		topic: {
			type: 'markdown',
			label: 'Topic',
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.TOPIC);
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, RoomSettingsEnum.TOPIC, value).then(function() {
					toastr.success(t('Room_topic_changed_successfully'));
					return RocketChat.callbacks.run('roomTopicChanged', room);
				});
			},
		},
		announcement: {
			type: 'markdown',
			label: 'Announcement',
			getValue() {
				return Template.instance().room.announcement;
			},
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.ANNOUNCEMENT);
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, RoomSettingsEnum.ANNOUNCEMENT, value).then(() => {
					toastr.success(t('Room_announcement_changed_successfully'));
					return RocketChat.callbacks.run('roomAnnouncementChanged', room);
				});
			},
		},
		description: {
			type: 'text',
			label: 'Description',
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.DESCRIPTION);
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, RoomSettingsEnum.DESCRIPTION, value).then(function() {
					return toastr.success(t('Room_description_changed_successfully'));
				});
			},
		},
		t: {
			type: 'boolean',
			// label() {
			// 	return ;
			// },
			isToggle: true,
			processing: new ReactiveVar(false),
			getValue() {
				return room.t === 'p';
			},
			disabled() {
				return room.default && !RocketChat.authz.hasRole(Meteor.userId(), 'admin');
			},
			message() {
				if (RocketChat.authz.hasAllPermission('edit-room', room._id) && room.default) {
					if (!RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
						return 'Room_type_of_default_rooms_cant_be_changed';
					}
				}
			},
			canView() {
				if (!['c', 'p'].includes(room.t)) {
					return false;
				} else if (room.t === 'p' && !RocketChat.authz.hasAllPermission('create-c')) {
					return false;
				} else if (room.t === 'c' && !RocketChat.authz.hasAllPermission('create-p')) {
					return false;
				}
				return true;
			},
			canEdit() {
				return (RocketChat.authz.hasAllPermission('edit-room', room._id) && !room.default) || RocketChat.authz.hasRole(Meteor.userId(), 'admin');
			},
			save(value) {
				const saveRoomSettings = () => {
					value = value ? 'p' : 'c';
					RocketChat.callbacks.run('roomTypeChanged', room);
					return call('saveRoomSettings', room._id, 'roomType', value).then(() => toastr.success(t('Room_type_changed_successfully')));
				};
				if (room.default) {
					if (RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
						return new Promise((resolve, reject) => {
							modal.open({
								title: t('Room_default_change_to_private_will_be_default_no_more'),
								type: 'warning',
								showCancelButton: true,
								confirmButtonColor: '#DD6B55',
								confirmButtonText: t('Yes'),
								cancelButtonText: t('Cancel'),
								closeOnConfirm: true,
								html: false,
							}, function(confirmed) {
								if (confirmed) {
									return resolve(saveRoomSettings());
								}
								return reject();
							});

						});
					}
					// return $('.channel-settings form [name=\'t\']').prop('checked', !!room.type === 'p');
				}
				return saveRoomSettings();
			},
		},
		ro: {
			type: 'boolean',
			label: 'Read_only',
			isToggle: true,
			processing: new ReactiveVar(false),
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.READ_ONLY);
			},
			canEdit() {
				return !room.broadcast && RocketChat.authz.hasAllPermission('set-readonly', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, RoomSettingsEnum.READ_ONLY, value).then(() => toastr.success(t('Read_only_changed_successfully')));
			},
		},
		reactWhenReadOnly: {
			type: 'boolean',
			label: 'React_when_read_only',
			isToggle: true,
			processing: new ReactiveVar(false),
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.REACT_WHEN_READ_ONLY);
			},
			canEdit() {
				return !room.broadcast && RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'reactWhenReadOnly', value).then(() => {
					toastr.success(t('React_when_read_only_changed_successfully'));
				});
			},
		},
		sysMes: {
			type: 'boolean',
			label: 'System_messages',
			isToggle: true,
			processing: new ReactiveVar(false),
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(
					room,
					RoomSettingsEnum.SYSTEM_MESSAGES
				);
			},
			getValue() {
				return room.sysMes !== false;
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'systemMessages', value).then(
					() => {
						toastr.success(
							t('System_messages_setting_changed_successfully')
						);
					}
				);
			},
		},
		archived: {
			type: 'boolean',
			label: 'Room_archivation_state_true',
			isToggle: true,
			processing: new ReactiveVar(false),
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE);
			},
			canEdit() {
				return RocketChat.authz.hasAtLeastOnePermission(['archive-room', 'unarchive-room'], room._id);
			},
			save(value) {
				return new Promise((resolve, reject) => {
					modal.open({
						title: t('Are_you_sure'),
						type: 'warning',
						showCancelButton: true,
						confirmButtonColor: '#DD6B55',
						confirmButtonText: value ? t('Yes_archive_it') : t('Yes_unarchive_it'),
						cancelButtonText: t('Cancel'),
						closeOnConfirm: false,
						html: false,
					}, function(confirmed) {
						if (confirmed) {
							const action = value ? 'archiveRoom' : 'unarchiveRoom';
							return resolve(call(action, room._id).then(() => {
								modal.open({
									title: value ? t('Room_archived') : t('Room_has_been_archived'),
									text: value ? t('Room_has_been_archived') : t('Room_has_been_unarchived'),
									type: 'success',
									timer: 2000,
									showConfirmButton: false,
								});
								return RocketChat.callbacks.run(action, room);
							}));
						}
						return reject();
					});
				});
			},
		},
		broadcast: {
			type: 'boolean',
			label: 'Broadcast_channel',
			isToggle: true,
			processing: new ReactiveVar(false),
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.BROADCAST);
			},
			canEdit() {
				return false;
			},
			save() {
				return Promise.resolve();
			},
		},
		joinCode: {
			type: 'text',
			label: 'Password',
			showingValue: new ReactiveVar(false),
			realValue: null,
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.JOIN_CODE) && RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			getValue() {
				if (this.showingValue.get()) {
					return this.realValue;
				}
				return room.joinCodeRequired ? '*****' : '';
			},
			showHideValue() {
				return room.joinCodeRequired;
			},
			cancelEditing() {
				this.showingValue.set(false);
				this.realValue = null;
			},
			async showValue(_room, forceShow = false) {
				if (this.showingValue.get()) {
					if (forceShow) {
						return;
					}
					this.showingValue.set(false);
					this.realValue = null;

					return null;
				}
				return call('getRoomJoinCode', room._id).then((result) => {
					this.realValue = result;
					this.showingValue.set(true);
				});
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'joinCode', value).then(function() {
					toastr.success(t('Room_password_changed_successfully'));
					return RocketChat.callbacks.run('roomCodeChanged', room);
				});
			},
		},
		retentionEnabled: {
			type: 'boolean',
			label: 'RetentionPolicyRoom_Enabled',
			processing: new ReactiveVar(false),
			getValue() {
				const { room = {} } = Template.instance() || {};
				return room.retention && room.retention.enabled;
			},
			canView() {
				return true;
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'retentionEnabled', value).then(() => toastr.success(t('Retention_setting_changed_successfully')));
			},
		},
		retentionOverrideGlobal: {
			type: 'boolean',
			label: 'RetentionPolicyRoom_OverrideGlobal',
			isToggle: true,
			processing: new ReactiveVar(false),
			getValue() {
				return Template.instance().room.retention && Template.instance().room.retention.overrideGlobal;
			},
			canView() {
				return true;
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-privileged-setting', room._id);
			},
			disabled() {
				return !RocketChat.authz.hasAllPermission('edit-privileged-setting', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'retentionOverrideGlobal', value).then(
					() => {
						toastr.success(
							t('Retention_setting_changed_successfully')
						);
					}
				);
			},
		},
		retentionMaxAge: {
			type: 'number',
			label: 'RetentionPolicyRoom_MaxAge',
			processing: new ReactiveVar(false),
			getValue() {
				const { room } = Template.instance();
				return Math.min(roomMaxAge(room), roomMaxAgeDefault(room.t));
			},
			canView() {
				return true;
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'retentionMaxAge', value).then(
					() => {
						toastr.success(
							t('Retention_setting_changed_successfully')
						);
					}
				);
			},
		},
		retentionExcludePinned: {
			type: 'boolean',
			label: 'RetentionPolicyRoom_ExcludePinned',
			isToggle: true,
			processing: new ReactiveVar(false),
			getValue() {
				return Template.instance().room.retention && Template.instance().room.retention.excludePinned;
			},
			canView() {
				return true;
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'retentionExcludePinned', value).then(
					() => {
						toastr.success(
							t('Retention_setting_changed_successfully')
						);
					}
				);
			},
		},
		retentionFilesOnly: {
			type: 'boolean',
			label: 'RetentionPolicyRoom_FilesOnly',
			isToggle: true,
			processing: new ReactiveVar(false),
			getValue() {
				return Template.instance().room.retention && Template.instance().room.retention.filesOnly;
			},
			canView() {
				return true;
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'retentionFilesOnly', value).then(
					() => {
						toastr.success(
							t('Retention_setting_changed_successfully')
						);
					}
				);
			},
		},
		encrypted: {
			type: 'boolean',
			label: 'Encrypted',
			isToggle: true,
			processing: new ReactiveVar(false),
			canView() {
				return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.E2E);
			},
			canEdit() {
				return RocketChat.authz.hasAllPermission('edit-room', room._id);
			},
			save(value) {
				return call('saveRoomSettings', room._id, 'encrypted', value).then(() => {
					toastr.success(
						t('Encrypted_setting_changed_successfully')
					);
				});
			},
		},
	};
	Object.keys(this.settings).forEach((key) => {
		const setting = this.settings[key];
		const def = setting.getValue ? setting.getValue(this.room) : (this.room[key] || false);
		setting.default = new ReactiveVar(def);
		setting.value = new ReactiveVar(def);
	});
});
Пример #19
0
		const { cl: canLeave, t: roomType } = Template.instance().room;
		return roomType !== 'd' && canLeave !== false;
	},
	canDeleteRoom() {
		const room = ChatRoom.findOne(this.rid, {
			fields: {
				t: 1,
			},
		});

		const roomType = room && room.t;
		return roomType && RocketChat.roomTypes.roomTypes[roomType].canBeDeleted(room);
	},
	canEditRoom() {
		const { _id } = Template.instance().room;
		return RocketChat.authz.hasAllPermission('edit-room', _id);
	},
	isDirectMessage() {
		const { room } = Template.instance();
		return room.t === 'd';
	},
};

function roomFilesOnly(room) {
	if (!room.retention) {
		return;
	}

	if (room.retention && room.retention.overrideGlobal) {
		return room.retention.filesOnly;
	}
Пример #20
0
		const { cl: canLeave, t: roomType } = Template.instance().room;
		return roomType !== 'd' && canLeave !== false;
	},
	canDeleteRoom() {
		const room = ChatRoom.findOne(this.rid, {
			fields: {
				t: 1
			}
		});

		const roomType = room && room.t;
		return roomType && RocketChat.roomTypes.roomTypes[roomType].canBeDeleted(room);
	},
	canEditRoom() {
		const { _id } = Template.instance().room;
		return RocketChat.authz.hasAllPermission('edit-room', _id);
	},
	isDirectMessage() {
		const { room } = Template.instance();
		return room.t === 'd';
	}
};

Template.channelSettingsEditing.events({
	'input .js-input'(e) {
		this.value.set(e.currentTarget.value);
	},
	'change .js-input-check'(e) {
		this.value.set(e.currentTarget.checked);
	},
	'click .js-reset'(e, t) {
import { Meteor } from 'meteor/meteor';
import { RocketChat } from 'meteor/rocketchat:lib';

Meteor.methods({
	deleteOutgoingIntegration(integrationId) {
		let integration;

		if (RocketChat.authz.hasPermission(this.userId, 'manage-integrations') || RocketChat.authz.hasPermission(this.userId, 'manage-integrations', 'bot')) {
			integration = RocketChat.models.Integrations.findOne(integrationId);
		} else if (RocketChat.authz.hasPermission(this.userId, 'manage-own-integrations') || RocketChat.authz.hasPermission(this.userId, 'manage-own-integrations', 'bot')) {
			integration = RocketChat.models.Integrations.findOne(integrationId, { fields: { '_createdBy._id': this.userId } });
		} else {
			throw new Meteor.Error('not_authorized', 'Unauthorized', { method: 'deleteOutgoingIntegration' });
		}

		if (!integration) {
			throw new Meteor.Error('error-invalid-integration', 'Invalid integration', { method: 'deleteOutgoingIntegration' });
		}

		RocketChat.models.Integrations.remove({ _id: integrationId });
		RocketChat.models.IntegrationHistory.removeByIntegrationId(integrationId);

		return true;
	},
});
Пример #22
0
import { Meteor } from 'meteor/meteor';
import { RocketChat } from 'meteor/rocketchat:lib';
import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom';

Meteor.methods({
	deleteEmojiCustom(emojiID) {
		let emoji = null;

		if (RocketChat.authz.hasPermission(this.userId, 'manage-emoji')) {
			emoji = RocketChat.models.EmojiCustom.findOneByID(emojiID);
		} else {
			throw new Meteor.Error('not_authorized');
		}

		if (emoji == null) {
			throw new Meteor.Error('Custom_Emoji_Error_Invalid_Emoji', 'Invalid emoji', { method: 'deleteEmojiCustom' });
		}

		RocketChatFileEmojiCustomInstance.deleteFile(encodeURIComponent(`${ emoji.name }.${ emoji.extension }`));
		RocketChat.models.EmojiCustom.removeByID(emojiID);
		RocketChat.Notifications.notifyLogged('deleteEmojiCustom', { emojiData: emoji });

		return true;
	},
});
Пример #23
0
						_id,
						ts: new Date().toISOString(),
					},
				});
			}

			return RocketChat.API.v1.failure();
		} catch (e) {
			return RocketChat.API.v1.failure(e.error);
		}
	},
});

RocketChat.API.v1.addRoute('livechat/visitor/:token/room', { authRequired: true }, {
	get() {
		if (!RocketChat.authz.hasPermission(this.userId, 'view-livechat-manager')) {
			return RocketChat.API.v1.unauthorized();
		}

		const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(this.urlParams.token, {
			fields: {
				name: 1,
				t: 1,
				cl: 1,
				u: 1,
				usernames: 1,
				servedBy: 1,
			},
		}).fetch();
		return RocketChat.API.v1.success({ rooms });
	},
Пример #24
0
import { Template } from 'meteor/templating';
import { RocketChat } from 'meteor/rocketchat:lib';

Template.integrationsNew.helpers({
	hasPermission() {
		return RocketChat.authz.hasAtLeastOnePermission(['manage-integrations', 'manage-own-integrations']);
	},
});
Пример #25
0
		if (!sub.open) {
			return RocketChat.API.v1.failure(`The channel, ${ findResult.name }, is already closed to the sender`);
		}

		Meteor.runAsUser(this.userId, () => {
			Meteor.call('hideRoom', findResult._id);
		});

		return RocketChat.API.v1.success();
	},
});

RocketChat.API.v1.addRoute('channels.counters', { authRequired: true }, {
	get() {
		const access = RocketChat.authz.hasPermission(this.userId, 'view-room-administration');
		const { userId } = this.requestParams();
		let user = this.userId;
		let unreads = null;
		let userMentions = null;
		let unreadsFrom = null;
		let joined = false;
		let msgs = null;
		let latest = null;
		let members = null;

		if (userId) {
			if (!access) {
				return RocketChat.API.v1.unauthorized();
			}
			user = userId;
Пример #26
0
			case 'webhook-incoming':
				Meteor.runAsUser(this.userId, () => {
					integration = Meteor.call('addIncomingIntegration', this.bodyParams);
				});
				break;
			default:
				return RocketChat.API.v1.failure('Invalid integration type.');
		}

		return RocketChat.API.v1.success({ integration });
	},
});

RocketChat.API.v1.addRoute('integrations.history', { authRequired: true }, {
	get() {
		if (!RocketChat.authz.hasPermission(this.userId, 'manage-integrations')) {
			return RocketChat.API.v1.unauthorized();
		}

		if (!this.queryParams.id || this.queryParams.id.trim() === '') {
			return RocketChat.API.v1.failure('Invalid integration id.');
		}

		const { id } = this.queryParams;
		const { offset, count } = this.getPaginationItems();
		const { sort, fields, query } = this.parseJsonQuery();

		const ourQuery = Object.assign({}, query, { 'integration._id': id });
		const history = RocketChat.models.IntegrationHistory.find(ourQuery, {
			sort: sort ? sort : { _updatedAt: -1 },
			skip: offset,
import { Meteor } from 'meteor/meteor';
import { RocketChat } from 'meteor/rocketchat:lib';

Meteor.methods({
	getSetupWizardParameters() {
		const userId = Meteor.userId();
		const userHasAdminRole = userId && RocketChat.authz.hasRole(userId, 'admin');

		if (!userHasAdminRole) {
			throw new Meteor.Error('error-not-allowed');
		}

		const settings = RocketChat.models.Settings.findSetupWizardSettings().fetch();
		const allowStandaloneServer = process.env.DEPLOY_PLATFORM !== 'rocket-cloud';

		return {
			settings,
			allowStandaloneServer,
		};
	},
});
Пример #28
0
import { Meteor } from 'meteor/meteor';
import { RocketChat } from 'meteor/rocketchat:lib';

Meteor.methods({
	'livechat:addAgent'(username) {
		if (!Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'view-livechat-manager')) {
			throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'livechat:addAgent' });
		}

		return RocketChat.Livechat.addAgent(username);
	},
});
Пример #29
0
import { Meteor } from 'meteor/meteor';
import { Importers } from 'meteor/rocketchat:importer';
import { RocketChat } from 'meteor/rocketchat:lib';

Meteor.methods({
	getImportProgress(key) {
		if (!Meteor.userId()) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getImportProgress' });
		}

		if (!RocketChat.authz.hasPermission(Meteor.userId(), 'run-import')) {
			throw new Meteor.Error('error-action-not-allowed', 'Importing is not allowed', { method: 'setupImporter' });
		}

		const importer = Importers.get(key);

		if (!importer) {
			throw new Meteor.Error('error-importer-not-defined', `The importer (${ key }) has no import class defined.`, { method: 'getImportProgress' });
		}

		if (!importer.instance) {
			return undefined;
		}

		return importer.instance.getProgress();
	},
});
Пример #30
0
RocketChat.integrations.validateOutgoing = function _validateOutgoing(integration, userId) {
	if (integration.channel && Match.test(integration.channel, String) && integration.channel.trim() === '') {
		delete integration.channel;
	}

	// Moved to it's own function to statisfy the complexity rule
	_verifyRequiredFields(integration);

	let channels = [];
	if (RocketChat.integrations.outgoingEvents[integration.event].use.channel) {
		if (!Match.test(integration.channel, String)) {
			throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', { function: 'validateOutgoing' });
		} else {
			channels = _.map(integration.channel.split(','), (channel) => s.trim(channel));

			for (const channel of channels) {
				if (!validChannelChars.includes(channel[0]) && !scopedChannels.includes(channel.toLowerCase())) {
					throw new Meteor.Error('error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', { function: 'validateOutgoing' });
				}
			}
		}
	} else if (!RocketChat.authz.hasPermission(userId, 'manage-integrations')) {
		throw new Meteor.Error('error-invalid-permissions', 'Invalid permission for required Integration creation.', { function: 'validateOutgoing' });
	}

	if (RocketChat.integrations.outgoingEvents[integration.event].use.triggerWords && integration.triggerWords) {
		if (!Match.test(integration.triggerWords, [String])) {
			throw new Meteor.Error('error-invalid-triggerWords', 'Invalid triggerWords', { function: 'validateOutgoing' });
		}

		integration.triggerWords.forEach((word, index) => {
			if (!word || word.trim() === '') {
				delete integration.triggerWords[index];
			}
		});

		integration.triggerWords = _.without(integration.triggerWords, [undefined]);
	} else {
		delete integration.triggerWords;
	}

	if (integration.scriptEnabled === true && integration.script && integration.script.trim() !== '') {
		try {
			const babelOptions = Object.assign(Babel.getDefaultOptions({ runtime: false }), { compact: true, minified: true, comments: false });

			integration.scriptCompiled = Babel.compile(integration.script, babelOptions).code;
			integration.scriptError = undefined;
		} catch (e) {
			integration.scriptCompiled = undefined;
			integration.scriptError = _.pick(e, 'name', 'message', 'stack');
		}
	}

	if (typeof integration.runOnEdits !== 'undefined') {
		// Verify this value is only true/false
		integration.runOnEdits = integration.runOnEdits === true;
	}

	_verifyUserHasPermissionForChannels(integration, userId, channels);
	_verifyRetryInformation(integration);

	const user = RocketChat.models.Users.findOne({ username: integration.username });

	if (!user) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user (did you delete the `rocket.cat` user?)', { function: 'validateOutgoing' });
	}

	integration.type = 'webhook-outgoing';
	integration.userId = user._id;
	integration.channel = channels;

	return integration;
};