Skip to content

Commit

Permalink
Merge pull request #8408 from RocketChat/rest-api-improve-json-query-…
Browse files Browse the repository at this point in the history
…helper

[FIX] Duplicate code in rest api letting in a few bugs with the rest api
# Conflicts:
#	packages/rocketchat-api/server/api.js
#	packages/rocketchat-api/server/v1/channels.js
#	packages/rocketchat-api/server/v1/groups.js
#	packages/rocketchat-api/server/v1/im.js
  • Loading branch information
rodrigok committed Oct 6, 2017
1 parent 3f1aa4e commit c56d52d
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 39 deletions.
20 changes: 19 additions & 1 deletion packages/rocketchat-api/server/api.js
Expand Up @@ -5,10 +5,28 @@ class API extends Restivus {
this.logger = new Logger(`API ${ properties.version ? properties.version : 'default' } Logger`, {});
this.authMethods = [];
this.helperMethods = new Map();
this.fieldSeparator = '.';
this.defaultFieldsToExclude = {
joinCode: 0,
$loki: 0,
meta: 0
meta: 0,
members: 0,
importIds: 0
};
this.limitedUserFieldsToExclude = {
avatarOrigin: 0,
emails: 0,
phone: 0,
statusConnection: 0,
createdAt: 0,
lastLogin: 0,
services: 0,
requirePasswordChange: 0,
requirePasswordChangeReason: 0,
roles: 0,
statusDefault: 0,
_updatedAt: 0,
customFields: 0
};

this._config.defaultOptionsEndpoint = function() {
Expand Down
6 changes: 3 additions & 3 deletions packages/rocketchat-api/server/v1/channels.js
Expand Up @@ -208,7 +208,7 @@ RocketChat.API.v1.addRoute('channels.getIntegrations', { authRequired: true }, {
sort: sort ? sort : { _createdAt: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
}).fetch();

return RocketChat.API.v1.success({
Expand Down Expand Up @@ -352,7 +352,7 @@ RocketChat.API.v1.addRoute('channels.list', { authRequired: true }, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
}).fetch();

return RocketChat.API.v1.success({
Expand All @@ -376,7 +376,7 @@ RocketChat.API.v1.addRoute('channels.list.joined', { authRequired: true }, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
});

return RocketChat.API.v1.success({
Expand Down
4 changes: 2 additions & 2 deletions packages/rocketchat-api/server/v1/groups.js
Expand Up @@ -168,7 +168,7 @@ RocketChat.API.v1.addRoute('groups.getIntegrations', { authRequired: true }, {
sort: sort ? sort : { _createdAt: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
}).fetch();

return RocketChat.API.v1.success({
Expand Down Expand Up @@ -284,7 +284,7 @@ RocketChat.API.v1.addRoute('groups.list', { authRequired: true }, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
});

return RocketChat.API.v1.success({
Expand Down
34 changes: 34 additions & 0 deletions packages/rocketchat-api/server/v1/helpers/parseJsonQuery.js
Expand Up @@ -19,6 +19,26 @@ RocketChat.API.v1.helperMethods.set('parseJsonQuery', function _parseJsonQuery()
}
}

// Verify the user's selected fields only contains ones which their role allows
if (typeof fields === 'object') {
let nonSelectableFields = Object.keys(RocketChat.API.v1.defaultFieldsToExclude);
if (!RocketChat.authz.hasPermission(this.userId, 'view-full-other-user-info') && this.request.route.includes('/v1/users.')) {
nonSelectableFields = nonSelectableFields.concat(Object.keys(RocketChat.API.v1.limitedUserFieldsToExclude));
}

Object.keys(fields).forEach((k) => {
if (nonSelectableFields.includes(k) || nonSelectableFields.includes(k.split(RocketChat.API.v1.fieldSeparator)[0])) {
delete fields[k];
}
});
}

// Limit the fields by default
fields = Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude);
if (!RocketChat.authz.hasPermission(this.userId, 'view-full-other-user-info') && this.request.route.includes('/v1/users.')) {
fields = Object.assign(fields, RocketChat.API.v1.limitedUserFieldsToExclude);
}

let query;
if (this.queryParams.query) {
try {
Expand All @@ -29,6 +49,20 @@ RocketChat.API.v1.helperMethods.set('parseJsonQuery', function _parseJsonQuery()
}
}

// Verify the user has permission to query the fields they are
if (typeof query === 'object') {
let nonQuerableFields = Object.keys(RocketChat.API.v1.defaultFieldsToExclude);
if (!RocketChat.authz.hasPermission(this.userId, 'view-full-other-user-info') && this.request.route.includes('/v1/users.')) {
nonQuerableFields = nonQuerableFields.concat(Object.keys(RocketChat.API.v1.limitedUserFieldsToExclude));
}

Object.keys(query).forEach((k) => {
if (nonQuerableFields.includes(k) || nonQuerableFields.includes(k.split(RocketChat.API.v1.fieldSeparator)[0])) {
delete query[k];
}
});
}

return {
sort,
fields,
Expand Down
6 changes: 3 additions & 3 deletions packages/rocketchat-api/server/v1/im.js
Expand Up @@ -106,7 +106,7 @@ RocketChat.API.v1.addRoute(['dm.messages.others', 'im.messages.others'], { authR
sort: sort ? sort : { ts: -1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
}).fetch();

return RocketChat.API.v1.success({
Expand All @@ -129,7 +129,7 @@ RocketChat.API.v1.addRoute(['dm.list', 'im.list'], { authRequired: true }, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
});

return RocketChat.API.v1.success({
Expand All @@ -156,7 +156,7 @@ RocketChat.API.v1.addRoute(['dm.list.everyone', 'im.list.everyone'], { authRequi
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
}).fetch();

return RocketChat.API.v1.success({
Expand Down
8 changes: 3 additions & 5 deletions packages/rocketchat-api/server/v1/stats.js
Expand Up @@ -25,20 +25,18 @@ RocketChat.API.v1.addRoute('statistics.list', { authRequired: true }, {
const { offset, count } = this.getPaginationItems();
const { sort, fields, query } = this.parseJsonQuery();

const ourQuery = Object.assign({}, query);

const statistics = RocketChat.models.Statistics.find(ourQuery, {
const statistics = RocketChat.models.Statistics.find(query, {
sort: sort ? sort : { name: 1 },
skip: offset,
limit: count,
fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude)
fields
}).fetch();

return RocketChat.API.v1.success({
statistics,
count: statistics.length,
offset,
total: RocketChat.models.Statistics.find(ourQuery).count()
total: RocketChat.models.Statistics.find(query).count()
});
}
});
28 changes: 3 additions & 25 deletions packages/rocketchat-api/server/v1/users.js
Expand Up @@ -112,40 +112,18 @@ RocketChat.API.v1.addRoute('users.list', { authRequired: true }, {
const { offset, count } = this.getPaginationItems();
const { sort, fields, query } = this.parseJsonQuery();

let fieldsToKeepFromRegularUsers;
if (!RocketChat.authz.hasPermission(this.userId, 'view-full-other-user-info')) {
fieldsToKeepFromRegularUsers = {
avatarOrigin: 0,
emails: 0,
phone: 0,
statusConnection: 0,
createdAt: 0,
lastLogin: 0,
services: 0,
requirePasswordChange: 0,
requirePasswordChangeReason: 0,
roles: 0,
statusDefault: 0,
_updatedAt: 0,
customFields: 0
};
}

const ourQuery = Object.assign({}, query);
const ourFields = Object.assign({}, fields, fieldsToKeepFromRegularUsers, RocketChat.API.v1.defaultFieldsToExclude);

const users = RocketChat.models.Users.find(ourQuery, {
const users = RocketChat.models.Users.find(query, {
sort: sort ? sort : { username: 1 },
skip: offset,
limit: count,
fields: ourFields
fields
}).fetch();

return RocketChat.API.v1.success({
users,
count: users.length,
offset,
total: RocketChat.models.Users.find(ourQuery).count()
total: RocketChat.models.Users.find(query).count()
});
}
});
Expand Down

0 comments on commit c56d52d

Please sign in to comment.