Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:RocketChat/Rocket.Chat into new/…
Browse files Browse the repository at this point in the history
…use_scrollableArea

* 'develop' of github.com:RocketChat/Rocket.Chat: (30 commits)
  [FIX] ie11 support (#16682)
  Regression: Show upload errors (#16681)
  [FIX] Delete messages while searching bug (#16568)
  Use insertSync
  [FIX] Image uploads (thumbnails) out of threads are not visible in regular message view (#16416)
  [FIX] Added an option to pin/unpin a thread message by admin (#16457)
  [CHORE] Look for Storybook stories on `app/` too (#16595)
  [IMPROVE] Removed the 'reply in thread' from thread replies (#16630)
  [FIX] Changed Opt_In message (#16631)
  [FIX] LDAP sync admin action was not syncing exisent users (#16671)
  [IMPROVE] Check agent status when starting a new conversation with an agent assigned (#16618)
  [FIX] Additional scroll when contextual bar is open (#16667)
  [FIX] Clear unread red line when the ESC key is pressed (#16668)
  [FIX] users.info endpoint not handling the error if the user does not exist (#16495)
  [NEW] Save default filters in the Omnichannel Current Chats list (#16653)
  Update app/utils/client/lib/RestApiClient.js
  Update app/utils/client/lib/RestApiClient.js
  send files over rest api
  [BUG][FIX] If InternalHubot_Username is undefined then rocket.cat should be default bot
  Improved isSingular function
  ...
  • Loading branch information
gabriellsh committed Feb 21, 2020
2 parents a7db70b + 1056e69 commit 256f5d3
Show file tree
Hide file tree
Showing 93 changed files with 393 additions and 235 deletions.
5 changes: 4 additions & 1 deletion .storybook/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ addParameters({
addDecorator(rocketChatDecorator);
addDecorator(withKnobs);

configure(require.context('../client', true, /\.stories\.js$/), module);
configure([
require.context('../app', true, /\.stories\.js$/),
require.context('../client', true, /\.stories\.js$/),
], module);
66 changes: 35 additions & 31 deletions app/api/server/v1/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,38 +59,45 @@ API.v1.addRoute('rooms.get', { authRequired: true }, {
},
});

API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, {
post() {
const room = Meteor.call('canAccessRoom', this.urlParams.rid, this.userId);
const getFiles = Meteor.wrapAsync(({ request }, callback) => {
const busboy = new Busboy({ headers: request.headers });
const files = [];

if (!room) {
return API.v1.unauthorized();
const fields = {};


busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
if (fieldname !== 'file') {
return callback(new Meteor.Error('invalid-field'));
}

const busboy = new Busboy({ headers: this.request.headers });
const files = [];
const fields = {};
const fileDate = [];
file.on('data', (data) => fileDate.push(data));

Meteor.wrapAsync((callback) => {
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
if (fieldname !== 'file') {
return callback(new Meteor.Error('invalid-field'));
}
file.on('end', () => {
files.push({ fieldname, file, filename, encoding, mimetype, fileBuffer: Buffer.concat(fileDate) });
});
});

const fileDate = [];
file.on('data', (data) => fileDate.push(data));
busboy.on('field', (fieldname, value) => { fields[fieldname] = value; });

file.on('end', () => {
files.push({ fieldname, file, filename, encoding, mimetype, fileBuffer: Buffer.concat(fileDate) });
});
});
busboy.on('finish', Meteor.bindEnvironment(() => callback(null, { files, fields })));

busboy.on('field', (fieldname, value) => { fields[fieldname] = value; });
request.pipe(busboy);
});

busboy.on('finish', Meteor.bindEnvironment(() => callback()));
API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, {
post() {
const room = Meteor.call('canAccessRoom', this.urlParams.rid, this.userId);

if (!room) {
return API.v1.unauthorized();
}

this.request.pipe(busboy);
})();

const { files, fields } = getFiles({
request: this.request,
});

if (files.length === 0) {
return API.v1.failure('File required');
Expand All @@ -102,8 +109,6 @@ API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, {

const file = files[0];

const fileStore = FileUpload.getStore('Uploads');

const details = {
name: file.filename,
size: file.fileBuffer.length,
Expand All @@ -112,18 +117,17 @@ API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, {
userId: this.userId,
};

let fileData = {};

Meteor.runAsUser(this.userId, () => {
const uploadedFile = Meteor.wrapAsync(fileStore.insert.bind(fileStore))(details, file.fileBuffer);
const fileData = Meteor.runAsUser(this.userId, () => {
const fileStore = FileUpload.getStore('Uploads');
const uploadedFile = fileStore.insertSync(details, file.fileBuffer);

uploadedFile.description = fields.description;

delete fields.description;

API.v1.success(Meteor.call('sendFileMessage', this.urlParams.rid, null, uploadedFile, fields));
Meteor.call('sendFileMessage', this.urlParams.rid, null, uploadedFile, fields);

fileData = uploadedFile;
return uploadedFile;
});

return API.v1.success({ message: Messages.getMessageByFileIdAndUsername(fileData._id, this.userId) });
Expand Down
2 changes: 1 addition & 1 deletion app/api/server/v1/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ API.v1.addRoute('users.info', { authRequired: true }, {
: getFullUserData(params);

if (!result || result.count() !== 1) {
return API.v1.failure(`Failed to get the user data for the userId of "${ this.userId }".`);
return API.v1.failure('User not found.');
}
const [user] = result.fetch();
const myself = user._id === this.userId;
Expand Down
4 changes: 2 additions & 2 deletions app/apps/client/admin/appInstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ Template.appInstall.events({
let result;

if (isUpdating) {
result = await APIClient.upload(`apps/${ t.isUpdatingId.get() }`, data);
result = await APIClient.upload(`apps/${ t.isUpdatingId.get() }`, data).promise;
} else {
result = await APIClient.upload('apps', data);
result = await APIClient.upload('apps', data).promise;
}

FlowRouter.go(`/admin/apps/${ result.app.id }?version=${ result.app.version }`);
Expand Down
2 changes: 2 additions & 0 deletions app/file-upload/server/lib/FileUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ export class FileUploadClass {
}

FileUpload.handlers[name] = this;

this.insertSync = Meteor.wrapAsync(this.insert, this);
}

getStore() {
Expand Down
7 changes: 6 additions & 1 deletion app/ldap/server/ldap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor';
import ldapjs from 'ldapjs';
import Bunyan from 'bunyan';

import { callbacks } from '../../callbacks/server';
import { settings } from '../../settings';
import { Logger } from '../../logger';

Expand Down Expand Up @@ -376,6 +377,8 @@ export default class LDAP {
searchAllPaged(BaseDN, options, page) {
this.bindIfNecessary();

({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options }));

const processPage = ({ entries, title, end, next }) => {
logger.search.info(title);
// Force LDAP idle to wait the record processing
Expand Down Expand Up @@ -425,8 +428,8 @@ export default class LDAP {
title: 'Final Page',
end: true,
});
entries = [];
} else if (entries.length) {
logger.search.info('Page');
processPage({
entries,
title: 'Page',
Expand All @@ -453,6 +456,8 @@ export default class LDAP {
searchAllAsync(BaseDN, options, callback) {
this.bindIfNecessary();

({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options }));

this.client.search(BaseDN, options, (error, res) => {
if (error) {
logger.search.error(error);
Expand Down
9 changes: 5 additions & 4 deletions app/ldap/server/sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SyncedCron } from 'meteor/littledata:synced-cron';
import _ from 'underscore';

import LDAP from './ldap';
import { callbacks } from '../../callbacks/server';
import { RocketChatFile } from '../../file';
import { settings } from '../../settings';
import { Notifications } from '../../notifications';
Expand All @@ -16,7 +17,7 @@ import { FileUpload } from '../../file-upload';
import { addUserToRoom, removeUserFromRoom, createRoom } from '../../lib/server/functions';


const logger = new Logger('LDAPSync', {});
export const logger = new Logger('LDAPSync', {});

export function isUserInLDAPGroup(ldap, ldapUser, user, ldapGroup) {
const syncUserRolesFilter = settings.get('LDAP_Sync_User_Data_Groups_Filter').trim();
Expand Down Expand Up @@ -531,7 +532,7 @@ export function importNewUsers(ldap) {
}));
}

function sync() {
export function sync() {
if (settings.get('LDAP_Enable') !== true) {
return;
}
Expand Down Expand Up @@ -562,9 +563,9 @@ function sync() {

if (ldapUser) {
syncUserData(user, ldapUser, ldap);
} else {
logger.info('Can\'t sync user', user.username);
}

callbacks.run('ldap.afterSyncExistentUser', { ldapUser, user });
});
}
} catch (error) {
Expand Down
4 changes: 2 additions & 2 deletions app/ldap/server/syncUsers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';

import { importNewUsers } from './sync';
import { sync } from './sync';
import { hasRole } from '../../authorization';
import { settings } from '../../settings';

Expand All @@ -21,7 +21,7 @@ Meteor.methods({

this.unblock();

importNewUsers();
sync();

return {
message: 'Sync_in_progress',
Expand Down
3 changes: 3 additions & 0 deletions app/lib/server/functions/getFullUserData.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export function getFullUserDataById({ userId, filterId }) {
export const getFullUserData = function({ userId, filter, limit: l }) {
const username = s.trim(filter);
const userToRetrieveFullUserData = username && Users.findOneByUsername(username, { fields: { username: 1 } });
if (!userToRetrieveFullUserData) {
return;
}

const isMyOwnInfo = userToRetrieveFullUserData && userToRetrieveFullUserData._id === userId;
const viewFullOtherUserInfo = hasPermission(userId, 'view-full-other-user-info');
Expand Down
46 changes: 46 additions & 0 deletions app/lib/server/functions/setUserActiveStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { check } from 'meteor/check';
import { Accounts } from 'meteor/accounts-base';

import * as Mailer from '../../../mailer';
import { Users, Subscriptions } from '../../../models';
import { settings } from '../../../settings';

export function setUserActiveStatus(userId, active) {
check(userId, String);
check(active, Boolean);

const user = Users.findOneById(userId);

if (!user) {
return false;
}

Users.setUserActive(userId, active);

if (user.username) {
Subscriptions.setArchivedByUsername(user.username, !active);
}

if (active === false) {
Users.unsetLoginTokens(userId);
} else {
Users.unsetReason(userId);
}
if (active && !settings.get('Accounts_Send_Email_When_Activating')) {
return true;
}
if (!active && !settings.get('Accounts_Send_Email_When_Deactivating')) {
return true;
}

const destinations = Array.isArray(user.emails) && user.emails.map((email) => `${ user.name || user.username }<${ email.address }>`);

const email = {
to: destinations,
from: settings.get('From_Email'),
subject: Accounts.emailTemplates.userActivated.subject({ active }),
html: Accounts.emailTemplates.userActivated.html({ active, name: user.name, username: user.username }),
};

Mailer.sendNoWrap(email);
}
16 changes: 7 additions & 9 deletions app/livechat/client/views/app/livechatCurrentChats.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<template name="livechatCurrentChats">
{{#requiresPermission 'view-livechat-current-chats'}}
<fieldset>
<form class="form-inline" method="post">
<form class="form-inline" id="form-filters" method="post">
<div class="livechat-group-filters-wrapper">
<div class="livechat-group-filters-container">
<div class="livechat-current-chats-standard-filters">
<div class="form-group">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Guest"}}</div>
<div class="rc-input__wrapper">
<input type="text" placeholder="{{_ "Name"}}" class="rc-input__element" name="name">
<input type="text" placeholder="{{_ "Name"}}" class="rc-input__element" id="name" name="name">
</div>
</label>
</div>
Expand All @@ -36,7 +36,7 @@
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Status"}}</div>
<div class="rc-select">
<select class="rc-select__element" name="status">
<select class="rc-select__element" id="status" name="status">
<option class="rc-select__option" value="">{{_ "All"}}</option>
<option class="rc-select__option" value="opened">{{_ "Opened"}}</option>
<option class="rc-select__option" value="closed">{{_ "Closed"}}</option>
Expand All @@ -49,7 +49,7 @@
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Department"}}</div>
<div class="rc-select">
<select class="rc-select__element" name="department">
<select class="rc-select__element" id="department" name="department">
<option class="rc-select__option" value="">{{_ "Select_a_department"}}</option>
{{#each departments}}
<option class="rc-select__option" value="{{_id}}">{{name}}</option>
Expand Down Expand Up @@ -108,11 +108,9 @@
<div class="livechat-group-filters-buttons">
<div class="rc-button__group">
<button class="rc-button rc-button--primary">{{_ "Filter"}}</button>
{{#if hasPopoverPermissions}}
<button class="livechat-current-chats-extra-actions">
{{> icon icon="menu" block="rc-icon--default-size"}}
</button>
{{/if}}
<button class="livechat-current-chats-extra-actions">
{{> icon icon="menu" block="rc-icon--default-size"}}
</button>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 256f5d3

Please sign in to comment.