[IMPROVE] Replace fullUserData publication by REST (#15650)

pull/16037/head
Marcos Spessatto Defendi 6 years ago committed by Diego Sampaio
parent 7928046561
commit b8383ceb5d
  1. 14
      app/api/server/v1/users.js
  2. 33
      app/lib/server/functions/getFullUserData.js
  3. 10
      app/models/client/models/FullUser.js
  4. 75
      app/ui-admin/client/users/adminUsers.js
  5. 32
      app/ui-flextab/client/tabs/userActions.js
  6. 6
      app/ui-flextab/client/tabs/userEdit.js
  7. 56
      app/ui-flextab/client/tabs/userInfo.js
  8. 1
      server/publications/fullUserData.js

@ -16,7 +16,7 @@ import {
setUserAvatar,
saveCustomFields,
} from '../../../lib';
import { getFullUserData } from '../../../lib/server/functions/getFullUserData';
import { getFullUserData, getFullUserDataById } from '../../../lib/server/functions/getFullUserData';
import { API } from '../api';
import { setStatusText } from '../../../lib/server';
import { findUsersToAutocomplete } from '../lib/users';
@ -153,14 +153,18 @@ API.v1.addRoute('users.getPresence', { authRequired: true }, {
API.v1.addRoute('users.info', { authRequired: true }, {
get() {
const { username } = this.getUserFromParams();
const { username, userId } = this.requestParams();
const { fields } = this.parseJsonQuery();
const result = getFullUserData({
const params = {
userId: this.userId,
filter: username,
limit: 1,
});
};
const result = userId
? getFullUserDataById({ userId: this.userId, filterId: userId })
: getFullUserData(params);
if (!result || result.count() !== 1) {
return API.v1.failure(`Failed to get the user data for the userId of "${ this.userId }".`);
}

@ -55,25 +55,42 @@ settings.get('Accounts_CustomFields', (key, value) => {
}
});
const getCustomFields = (canViewAllInfo) => (canViewAllInfo ? customFields : publicCustomFields);
const getFields = (canViewAllInfo) => ({
...defaultFields,
...canViewAllInfo && fullFields,
...getCustomFields(canViewAllInfo),
});
export function getFullUserDataById({ userId, filterId }) {
const canViewAllInfo = userId === filterId || hasPermission(userId, 'view-full-other-user-info');
const fields = getFields(canViewAllInfo);
const options = {
fields,
};
return Users.findById(filterId, options);
}
export const getFullUserData = function({ userId, filter, limit: l }) {
const username = s.trim(filter);
const userToRetrieveFullUserData = Users.findOneByUsername(username, { fields: { username: 1 } });
const userToRetrieveFullUserData = username && Users.findOneByUsername(username, { fields: { username: 1 } });
const isMyOwnInfo = userToRetrieveFullUserData && userToRetrieveFullUserData._id === userId;
const viewFullOtherUserInfo = hasPermission(userId, 'view-full-other-user-info');
const canViewAllInfo = isMyOwnInfo || viewFullOtherUserInfo;
const limit = !viewFullOtherUserInfo ? 1 : l;
if (!username && limit <= 1) {
return undefined;
}
const _customFields = isMyOwnInfo || viewFullOtherUserInfo
? customFields
: publicCustomFields;
const fields = isMyOwnInfo || viewFullOtherUserInfo
? { ...defaultFields, ...fullFields, ..._customFields }
: { ...defaultFields, ..._customFields };
const fields = getFields(canViewAllInfo);
const options = {
fields,

@ -1,10 +0,0 @@
import { Base } from './_Base';
class FullUser extends Base {
constructor() {
super();
this._initModel('full_user');
}
}
export default new FullUser();

@ -3,10 +3,11 @@ import { Tracker } from 'meteor/tracker';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import _ from 'underscore';
import s from 'underscore.string';
import { SideNav, TabBar, RocketChatTabBar } from '../../../ui-utils';
import FullUser from '../../../models/client/models/FullUser';
import { APIClient } from '../../../utils/client';
const USERS_COUNT = 50;
Template.adminUsers.helpers({
searchText() {
@ -18,7 +19,7 @@ Template.adminUsers.helpers({
return instance.ready && instance.ready.get();
},
users() {
return Template.instance().users();
return Template.instance().users.get();
},
isLoading() {
const instance = Template.instance();
@ -29,8 +30,8 @@ Template.adminUsers.helpers({
hasMore() {
const instance = Template.instance();
const users = instance.users();
if (instance.limit && instance.limit.get() && users && users.length) {
return instance.limit.get() === users.length;
if (instance.offset && instance.offset.get() && users && users.length) {
return instance.offset.get() === users.length;
}
},
emailAddress() {
@ -49,7 +50,7 @@ Template.adminUsers.helpers({
currentTarget.offsetHeight + currentTarget.scrollTop
>= currentTarget.scrollHeight - 100
) {
return instance.limit.set(instance.limit.get() + 50);
return instance.offset.set(instance.offset.get() + USERS_COUNT);
}
};
},
@ -66,12 +67,14 @@ Template.adminUsers.helpers({
Template.adminUsers.onCreated(function() {
const instance = this;
this.limit = new ReactiveVar(50);
this.offset = new ReactiveVar(0);
this.filter = new ReactiveVar('');
this.ready = new ReactiveVar(true);
this.tabBar = new RocketChatTabBar();
this.tabBar.showGroup(FlowRouter.current().route.name);
this.tabBarData = new ReactiveVar();
this.users = new ReactiveVar([]);
TabBar.addButton({
groups: ['admin-users'],
id: 'invite-user',
@ -96,33 +99,36 @@ Template.adminUsers.onCreated(function() {
template: 'adminUserInfo',
order: 3,
});
this.autorun(function() {
const filter = instance.filter.get();
const limit = instance.limit.get();
const subscription = instance.subscribe('fullUserData', filter, limit);
instance.ready.set(subscription.ready());
});
this.users = function() {
let filter;
let query;
if (instance.filter && instance.filter.get()) {
filter = s.trim(instance.filter.get());
}
this.loadUsers = async (filter, offset) => {
this.ready.set(false);
const query = {
$or: [
{ 'emails.address': { $regex: filter, $options: 'i' } },
{ username: { $regex: filter, $options: 'i' } },
{ name: { $regex: filter, $options: 'i' } },
],
};
let url = `users.list?count=${ USERS_COUNT }&offset=${ offset }`;
if (filter) {
const filterReg = new RegExp(s.escapeRegExp(filter), 'i');
query = { $or: [{ username: filterReg }, { name: filterReg }, { 'emails.address': filterReg }] };
url += `&query=${ JSON.stringify(query) }`;
}
const { users } = await APIClient.v1.get(url);
if (offset === 0) {
this.users.set(users);
} else {
query = {};
this.users.set(this.users.get().concat(users));
}
query.type = {
$in: ['user', 'bot'],
};
const limit = instance.limit && instance.limit.get();
return FullUser.find(query, { limit, sort: { username: 1, name: 1 } }).fetch();
this.ready.set(true);
};
this.autorun(async () => {
const filter = instance.filter.get();
const offset = instance.offset.get();
this.loadUsers(filter, offset);
});
});
Template.adminUsers.onRendered(function() {
@ -145,10 +151,19 @@ Template.adminUsers.events({
e.stopPropagation();
e.preventDefault();
t.filter.set(e.currentTarget.value);
t.offset.set(0);
}, DEBOUNCE_TIME_FOR_SEARCH_USERS_IN_MS),
'click .user-info'(e, instance) {
e.preventDefault();
instance.tabBarData.set(FullUser.findOne(this._id));
instance.tabBarData.set({
...instance.users.get().find((user) => user._id === this._id),
onChange() {
const filter = instance.filter.get();
const offset = instance.offset.get();
instance.loadUsers(filter, offset);
},
});
instance.tabBar.open('admin-user-info');
},
'click .info-tabs button'(e) {
@ -161,6 +176,6 @@ Template.adminUsers.events({
'click .load-more'(e, t) {
e.preventDefault();
e.stopPropagation();
t.limit.set(t.limit.get() + 50);
t.offset.set(t.offset.get() + USERS_COUNT);
},
});

@ -10,7 +10,7 @@ import { ChatRoom, ChatSubscription, RoomRoles, Subscriptions } from '../../../m
import { modal } from '../../../ui-utils';
import { t, handleError, roomTypes } from '../../../utils';
import { settings } from '../../../settings';
import { hasPermission, hasAllPermission, hasRole, userHasAllPermission } from '../../../authorization';
import { hasPermission, hasAllPermission, userHasAllPermission } from '../../../authorization';
const canSetLeader = () => hasAllPermission('set-leader', Session.get('openedRoom'));
@ -75,7 +75,7 @@ export const getActions = ({ user, directActions, hideAdminControls }) => {
return user && user.username === username;
};
const hasAdminRole = () => user && user._id && hasRole(user._id, 'admin');
const hasAdminRole = () => user && user.roles && user.roles.find((role) => role === 'admin');
const getUser = function getUser(fn, ...args) {
if (!user) {
@ -462,14 +462,24 @@ export const getActions = ({ user, directActions, hideAdminControls }) => {
group: 'admin',
icon: 'key',
name: t('Remove_Admin'),
action: prevent(getUser, ({ _id }) => Meteor.call('setAdminStatus', _id, false, success(() => toastr.success(t('User_is_no_longer_an_admin'))))),
action: prevent(getUser, ({ _id }) =>
Meteor.call('setAdminStatus', _id, false, success(() => {
toastr.success(t('User_is_no_longer_an_admin'));
user.roles = user.roles.filter((role) => role !== 'admin');
})),
),
};
}
return {
group: 'admin',
icon: 'key',
name: t('Make_Admin'),
action: prevent(getUser, ({ _id }) => Meteor.call('setAdminStatus', _id, true, success(() => toastr.success(t('User_is_now_an_admin'))))),
action: prevent(getUser, (user) =>
Meteor.call('setAdminStatus', user._id, true, success(() => {
toastr.success(t('User_is_now_an_admin'));
user.roles.push('admin');
})),
),
};
}, () => {
if (hideAdminControls || !hasPermission('edit-other-user-active-status')) {
@ -482,7 +492,12 @@ export const getActions = ({ user, directActions, hideAdminControls }) => {
id: 'deactivate',
name: t('Deactivate'),
modifier: 'alert',
action: prevent(getUser, ({ _id }) => Meteor.call('setUserActiveStatus', _id, false, success(() => toastr.success(t('User_has_been_deactivated'))))),
action: prevent(getUser, (user) =>
Meteor.call('setUserActiveStatus', user._id, false, success(() => {
toastr.success(t('User_has_been_deactivated'));
user.active = false;
})),
),
};
}
return {
@ -490,7 +505,12 @@ export const getActions = ({ user, directActions, hideAdminControls }) => {
icon: 'user',
id: 'activate',
name: t('Activate'),
action: prevent(getUser, ({ _id }) => Meteor.call('setUserActiveStatus', _id, true, success(() => toastr.success(t('User_has_been_activated'))))),
action: prevent(getUser, (user) =>
Meteor.call('setUserActiveStatus', user._id, true, success(() => {
toastr.success(t('User_has_been_activated'));
user.active = true;
})),
),
};
}];

@ -183,11 +183,11 @@ Template.userEdit.onCreated(function() {
const { tabBar } = Template.currentData();
this.cancel = (form, username) => {
this.cancel = (form, data) => {
form.reset();
this.$('input[type=checkbox]').prop('checked', true);
if (this.user) {
return this.data.back(username);
return this.data.back(data);
}
return tabBar.close();
};
@ -284,7 +284,7 @@ Template.userEdit.onCreated(function() {
return handleError(error);
}
toastr.success(userData._id ? t('User_updated_successfully') : t('User_added_successfully'));
this.cancel(form, userData.username);
this.cancel(form, userData);
});
};
});

@ -11,10 +11,9 @@ import { popover } from '../../../ui-utils';
import { templateVarHandler } from '../../../utils';
import { RoomRoles, UserRoles, Roles } from '../../../models';
import { settings } from '../../../settings';
import FullUser from '../../../models/client/models/FullUser';
import { getActions } from './userActions';
import './userInfo.html';
import { APIClient } from '../../../utils/client';
const shownActionsCount = 2;
@ -168,9 +167,14 @@ Template.userInfo.helpers({
const data = Template.currentData();
return {
user: instance.user.get(),
back(username) {
back({ _id, username }) {
instance.editingUser.set();
if (_id) {
data.onChange && data.onChange();
return instance.loadUser({ _id });
}
if (username != null) {
const user = instance.user.get();
if ((user != null ? user.username : undefined) !== username) {
@ -265,47 +269,39 @@ Template.userInfo.onCreated(function() {
});
this.editingUser = new ReactiveVar();
this.loadingUserInfo = new ReactiveVar(true);
this.loadedUsername = new ReactiveVar();
this.tabBar = Template.currentData().tabBar;
this.nowInterval = setInterval(() => this.now.set(moment()), 30000);
this.autorun(() => {
const username = this.loadedUsername.get();
this.loadUser = async ({ _id, username }) => {
this.loadingUserInfo.set(true);
if (username == null) {
this.loadingUserInfo.set(false);
return;
const params = {};
if (_id != null) {
params.userId = _id;
} else if (username != null) {
params.username = username;
}
this.loadingUserInfo.set(true);
const { user } = await APIClient.v1.get('users.info', params);
this.user.set(user);
this.loadingUserInfo.set(false);
};
return this.subscribe('fullUserData', username, 1, () => this.loadingUserInfo.set(false));
});
this.autorun(() => {
this.autorun(async () => {
const data = Template.currentData();
if (data.clear != null) {
this.clear = data.clear;
if (!data) {
return;
}
});
this.autorun(() => {
const data = Template.currentData();
const user = this.user.get();
return this.loadedUsername.set((user != null ? user.username : undefined) || (data != null ? data.username : undefined));
this.loadUser(data);
});
return this.autorun(() => {
let filter;
this.autorun(() => {
const data = Template.currentData();
if (data && data.username != null) {
filter = { username: data.username };
} else if (data && data._id != null) {
filter = { _id: data._id };
if (data.clear != null) {
this.clear = data.clear;
}
const user = FullUser.findOne(filter);
return this.user.set(user);
});
});

@ -3,6 +3,7 @@ import { Meteor } from 'meteor/meteor';
import { getFullUserData } from '../../app/lib';
Meteor.publish('fullUserData', function(filter, limit) {
console.warn('The publication "fullUserData" is deprecated and will be removed after version v3.0.0');
if (!this.userId) {
return this.ready();
}

Loading…
Cancel
Save