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
…default-favorite-channels

* 'develop' of github.com:RocketChat/Rocket.Chat: (27 commits)
  [FIX] Missing edited icon in newly created messages (#16484)
  Regression: allow private channels to hide system messages  (#16483)
  Regression: Fix uikit modal closing on click (#16475)
  Regression: Fix undefined presence after reconnect (#16477)
  [FIX] Read Message after receive a message and the room is opened (#16473)
  [FIX] Send message with pending messages (#16474)
  Fix tests (#16469)
  Bump version to 3.0.0-develop
  [NEW] Button to download admin server info (#16059)
  Revert importer streamed uploads (#16465)
  [NEW] UiKit - Interactive UI elements for Rocket.Chat Apps (#16048)
  [FIX] Result of get avatar from url can be null (#16123)
  [IMPROVE] Request user presence on demand (#16348)
  [IMPROVE] Major overhaul on data importers (#16279)
  [BREAK] Filter System messages per room (#16369)
  Regression: Fix app user status change for non-existing user (#16458)
  [FIX] `stdout` streamer infinite loop (#16452)
  Regression: Fix sending a message not scrolling to bottom (#16451)
  LingoHub based on develop (#16450)
  [IMPROVE] Changes App user's status when the app was enabled/disabled (#16392)
  ...
  • Loading branch information
gabriellsh committed Feb 5, 2020
2 parents 1c5e65b + 142efe4 commit 5623364
Show file tree
Hide file tree
Showing 164 changed files with 14,119 additions and 13,921 deletions.
2 changes: 1 addition & 1 deletion .docker/Dockerfile.rhel
@@ -1,6 +1,6 @@
FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7

ENV RC_VERSION 2.5.0-develop
ENV RC_VERSION 3.0.0-develop

MAINTAINER buildmaster@rocket.chat

Expand Down
42 changes: 23 additions & 19 deletions .github/workflows/build_and_test.yml
Expand Up @@ -146,13 +146,17 @@ jobs:
cd /tmp
tar czf Rocket.Chat.test.tar.gz ./build-test
- name: Store builds
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 cp /tmp/Rocket.Chat.test.tar.gz s3://rocketchatbuild/builds/$GITHUB_SHA/
aws s3 cp /tmp/build/Rocket.Chat.tar.gz s3://rocketchatbuild/builds/$GITHUB_SHA/
- name: Store build for tests
uses: actions/upload-artifact@v1
with:
name: build-test
path: /tmp/Rocket.Chat.test.tar.gz

- name: Store build
uses: actions/upload-artifact@v1
with:
name: build
path: /tmp/build

test:
runs-on: ubuntu-16.04
Expand All @@ -170,10 +174,10 @@ jobs:
mongoDBVersion: ${{ matrix.mongodb-version }} --noprealloc --smallfiles --replSet=rs0

- name: Restore build for tests
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: aws s3 cp s3://rocketchatbuild/builds/$GITHUB_SHA/Rocket.Chat.test.tar.gz /tmp/
uses: actions/download-artifact@v1
with:
name: build-test
path: /tmp

- name: Decompress build
run: |
Expand Down Expand Up @@ -349,10 +353,10 @@ jobs:
- uses: actions/checkout@v1

- name: Restore build
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: aws s3 cp s3://rocketchatbuild/builds/$GITHUB_SHA/Rocket.Chat.tar.gz /tmp/build/
uses: actions/download-artifact@v1
with:
name: build
path: /tmp/build

- name: Publish assets
env:
Expand Down Expand Up @@ -401,10 +405,10 @@ jobs:
- uses: actions/checkout@v1

- name: Restore build
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: aws s3 cp s3://rocketchatbuild/builds/$GITHUB_SHA/Rocket.Chat.tar.gz /tmp/build/
uses: actions/download-artifact@v1
with:
name: build
path: /tmp/build

- name: Unpack build
env:
Expand Down
35 changes: 30 additions & 5 deletions app/api/server/v1/commands.js
Expand Up @@ -51,7 +51,7 @@ API.v1.addRoute('commands.list', { authRequired: true }, {
},
});

// Expects a body of: { command: 'gimme', params: 'any string value', roomId: 'value' }
// Expects a body of: { command: 'gimme', params: 'any string value', roomId: 'value', triggerId: 'value' }
API.v1.addRoute('commands.run', { authRequired: true }, {
post() {
const body = this.bodyParams;
Expand All @@ -74,7 +74,7 @@ API.v1.addRoute('commands.run', { authRequired: true }, {
}

const cmd = body.command.toLowerCase();
if (!slashCommands.commands[body.command.toLowerCase()]) {
if (!slashCommands.commands[cmd]) {
return API.v1.failure('The command provided does not exist (or is disabled).');
}

Expand All @@ -96,7 +96,9 @@ API.v1.addRoute('commands.run', { authRequired: true }, {
message.tmid = body.tmid;
}

const result = Meteor.runAsUser(user._id, () => slashCommands.run(cmd, params, message));
const { triggerId } = body;

const result = Meteor.runAsUser(user._id, () => slashCommands.run(cmd, params, message, triggerId));

return API.v1.success({ result });
},
Expand Down Expand Up @@ -137,7 +139,7 @@ API.v1.addRoute('commands.preview', { authRequired: true }, {

return API.v1.success({ preview });
},
// Expects a body format of: { command: 'giphy', params: 'mine', roomId: 'value', previewItem: { id: 'sadf8' type: 'image', value: 'https://dev.null/gif } }
// Expects a body format of: { command: 'giphy', params: 'mine', roomId: 'value', tmid: 'value', triggerId: 'value', previewItem: { id: 'sadf8' type: 'image', value: 'https://dev.null/gif' } }
post() {
const body = this.bodyParams;
const user = this.getLoggedInUser();
Expand All @@ -162,6 +164,14 @@ API.v1.addRoute('commands.preview', { authRequired: true }, {
return API.v1.failure('The preview item being executed is in the wrong format.');
}

if (body.tmid && typeof body.tmid !== 'string') {
return API.v1.failure('The tmid parameter when provided must be a string.');
}

if (body.triggerId && typeof body.triggerId !== 'string') {
return API.v1.failure('The triggerId parameter when provided must be a string.');
}

const cmd = body.command.toLowerCase();
if (!slashCommands.commands[cmd]) {
return API.v1.failure('The command provided does not exist (or is disabled).');
Expand All @@ -171,9 +181,24 @@ API.v1.addRoute('commands.preview', { authRequired: true }, {
Meteor.call('canAccessRoom', body.roomId, user._id);

const params = body.params ? body.params : '';
const message = {
rid: body.roomId,
};

if (body.tmid) {
const thread = Messages.findOneById(body.tmid);
if (!thread || thread.rid !== body.roomId) {
return API.v1.failure('Invalid thread.');
}
message.tmid = body.tmid;
}

Meteor.runAsUser(user._id, () => {
Meteor.call('executeSlashCommandPreview', { cmd, params, msg: { rid: body.roomId } }, body.previewItem);
Meteor.call('executeSlashCommandPreview', {
cmd,
params,
msg: { rid: body.roomId, tmid: body.tmid },
}, body.previewItem, body.triggerId);
});

return API.v1.success();
Expand Down
71 changes: 69 additions & 2 deletions app/api/server/v1/import.js
@@ -1,6 +1,9 @@
import { Meteor } from 'meteor/meteor';

import { API } from '../api';
import { hasPermission } from '../../../authorization/server';
import { Imports } from '../../../models/server';
import { Importers } from '../../../importer/server';

API.v1.addRoute('uploadImportFile', { authRequired: true }, {
post() {
Expand Down Expand Up @@ -28,17 +31,38 @@ API.v1.addRoute('downloadPublicImportFile', { authRequired: true }, {

});

API.v1.addRoute('startImport', { authRequired: true }, {
post() {
const { input } = this.bodyParams;

Meteor.runAsUser(this.userId, () => {
API.v1.success(Meteor.call('startImport', input));
});

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

API.v1.addRoute('getImportFileData', { authRequired: true }, {
get() {
const { importerKey } = this.requestParams();
let result;
Meteor.runAsUser(this.userId, () => {
result = Meteor.call('getImportFileData', importerKey);
result = Meteor.call('getImportFileData');
});

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

API.v1.addRoute('getImportProgress', { authRequired: true }, {
get() {
let result;
Meteor.runAsUser(this.userId, () => {
result = Meteor.call('getImportProgress');
});

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

API.v1.addRoute('getLatestImportOperations', { authRequired: true }, {
Expand All @@ -49,3 +73,46 @@ API.v1.addRoute('getLatestImportOperations', { authRequired: true }, {
return API.v1.success(result);
},
});

API.v1.addRoute('downloadPendingFiles', { authRequired: true }, {
post() {
if (!this.userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'downloadPendingFiles' });
}

if (!hasPermission(this.userId, 'run-import')) {
throw new Meteor.Error('not_authorized');
}

const importer = Importers.get('pending-files');
if (!importer) {
throw new Meteor.Error('error-importer-not-defined', 'The Pending File Importer was not found.', { method: 'downloadPendingFiles' });
}

importer.instance = new importer.importer(importer); // eslint-disable-line new-cap
const count = importer.instance.prepareFileCount();

return API.v1.success({
success: true,
count,
});
},
});

API.v1.addRoute('getCurrentImportOperation', { authRequired: true }, {
get() {
if (!this.userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getCurrentImportOperation' });
}

if (!hasPermission(this.userId, 'run-import')) {
throw new Meteor.Error('not_authorized');
}

const operation = Imports.findLastImport();
return API.v1.success({
success: true,
operation,
});
},
});
50 changes: 16 additions & 34 deletions app/api/server/v1/stats.js
@@ -1,48 +1,30 @@
import { Meteor } from 'meteor/meteor';

import { hasPermission } from '../../../authorization';
import { Statistics } from '../../../models';
import { API } from '../api';
import { getStatistics, getLastStatistics } from '../../../statistics/server';

API.v1.addRoute('statistics', { authRequired: true }, {
get() {
let refresh = false;
if (typeof this.queryParams.refresh !== 'undefined' && this.queryParams.refresh === 'true') {
refresh = true;
}

let stats;
Meteor.runAsUser(this.userId, () => {
stats = Meteor.call('getStatistics', refresh);
});

return API.v1.success({
statistics: stats,
});
const { refresh } = this.requestParams();
return API.v1.success(Promise.await(getLastStatistics({
userId: this.userId,
refresh: refresh && refresh === 'true',
})));
},
});

API.v1.addRoute('statistics.list', { authRequired: true }, {
get() {
if (!hasPermission(this.userId, 'view-statistics')) {
return API.v1.unauthorized();
}

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

const statistics = Statistics.find(query, {
sort: sort || { name: 1 },
skip: offset,
limit: count,
fields,
}).fetch();

return API.v1.success({
statistics,
count: statistics.length,
offset,
total: Statistics.find(query).count(),
});
return API.v1.success(Promise.await(getStatistics({
userId: this.userId,
query,
pagination: {
offset,
count,
sort,
fields,
},
})));
},
});
9 changes: 8 additions & 1 deletion app/api/server/v1/users.js
Expand Up @@ -647,7 +647,7 @@ API.v1.addRoute('users.removePersonalAccessToken', { authRequired: true }, {

API.v1.addRoute('users.presence', { authRequired: true }, {
get() {
const { from } = this.queryParams;
const { from, ids } = this.queryParams;

const options = {
fields: {
Expand All @@ -659,6 +659,13 @@ API.v1.addRoute('users.presence', { authRequired: true }, {
},
};

if (ids) {
return API.v1.success({
users: Users.findNotOfflineByIds(Array.isArray(ids) ? ids : ids.split(','), options).fetch(),
full: false,
});
}

if (from) {
const ts = new Date(from);
const diff = (Date.now() - ts) / 1000 / 60;
Expand Down
18 changes: 18 additions & 0 deletions app/apps/server/bridges/activation.js
@@ -1,3 +1,7 @@
import { STATUS_MAP } from '../../../../imports/users-presence/server/activeUsers';
import { Users } from '../../../models/server';
import { Notifications } from '../../../notifications/server';

export class AppActivationBridge {
constructor(orch) {
this.orch = orch;
Expand All @@ -16,6 +20,20 @@ export class AppActivationBridge {
}

async appStatusChanged(app, status) {
const user = Users.findOneByAppId(app.getID(), { fields: { username: 1 } });

if (user) {
const { _id, username } = user;
const userStatus = ['auto_enabled', 'manually_enabled'].includes(status) ? 'online' : 'offline';

Users.updateStatusById(_id, userStatus);
Notifications.notifyLogged('user-status', [
_id,
username,
STATUS_MAP[userStatus],
]);
}

await this.orch.getNotifier().appStatusUpdated(app.getID(), status);
}
}
6 changes: 6 additions & 0 deletions app/apps/server/bridges/bridges.js
Expand Up @@ -15,6 +15,7 @@ import { AppSettingBridge } from './settings';
import { AppUserBridge } from './users';
import { AppLivechatBridge } from './livechat';
import { AppUploadBridge } from './uploads';
import { UiInteractionBridge } from './uiInteraction';

export class RealAppBridges extends AppBridges {
constructor(orch) {
Expand All @@ -35,6 +36,7 @@ export class RealAppBridges extends AppBridges {
this._userBridge = new AppUserBridge(orch);
this._livechatBridge = new AppLivechatBridge(orch);
this._uploadBridge = new AppUploadBridge(orch);
this._uiInteractionBridge = new UiInteractionBridge(orch);
}

getCommandBridge() {
Expand Down Expand Up @@ -96,4 +98,8 @@ export class RealAppBridges extends AppBridges {
getUploadBridge() {
return this._uploadBridge;
}

getUiInteractionBridge() {
return this._uiInteractionBridge;
}
}

0 comments on commit 5623364

Please sign in to comment.