Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: New user panel: First phase #30236

Closed
wants to merge 92 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
c30b478
feat: User Panel > Tab ALL (#29622)
hugocostadev Aug 30, 2023
3b1db79
Merge branch 'develop' into feat/user-panel
rique223 Aug 31, 2023
ec62678
Merge branch 'develop' into feat/user-panel
rique223 Sep 18, 2023
61681ff
Merge branch 'develop' into feat/user-panel
rique223 Sep 27, 2023
90da483
feat: Implement users page active tab (#30242)
rique223 Oct 4, 2023
964e9e4
style: :lipstick: Review
rique223 Oct 5, 2023
df6c31d
Merge branch 'develop' into feat/user-panel
rique223 Oct 18, 2023
809ca6c
feat: New create user contextual bar (#30582)
rique223 Oct 23, 2023
3c793c8
feat: pending tab new (#30666)
felipe-rod123 Oct 30, 2023
27de920
Merge branch 'develop' into feat/user-panel
rique223 Oct 30, 2023
32963e1
Merge branch 'develop' into feat/user-panel
rique223 Oct 31, 2023
86c6469
chore: Change user created page message from string to states (#30806)
rique223 Nov 3, 2023
c6b4b54
feat: add endpoint to get active/inactive users and filter by role
tapiarafael Nov 3, 2023
2cb1c1d
feat: add endpoint to send welcome email
tapiarafael Nov 3, 2023
9f14c8f
feat: add pending status to the endpoint
tapiarafael Nov 6, 2023
2bff799
fix: change param name to match frontend tabs
tapiarafael Nov 7, 2023
42470e9
refactor: remove meteor dependency
tapiarafael Nov 7, 2023
d473fe2
Merge branch 'develop' into feat/user-panel
rique223 Nov 7, 2023
b0f15fe
refactor: move query to model
tapiarafael Nov 7, 2023
efa2f23
refactor: remove deprecated `field` query param
tapiarafael Nov 7, 2023
da564d6
Merge branch 'develop' into feat/new-users-tab-endpoints
tapiarafael Nov 7, 2023
e8b6d3c
Merge branch 'feat/user-panel' into feat/new-users-tab-endpoints
tapiarafael Nov 7, 2023
ade3c32
Create serious-poets-smash.md
tapiarafael Nov 7, 2023
95ffefc
test: list users tab
tapiarafael Nov 7, 2023
626ed7c
test: fix expect to avoid being affect by other tests
tapiarafael Nov 7, 2023
32199ce
fix: changes requested
tapiarafael Nov 13, 2023
66a327f
fix: use ajv to validate request params
tapiarafael Nov 16, 2023
70bbfc5
fix: set role as optional param
tapiarafael Nov 16, 2023
9a3e60b
test: check if user has permission
tapiarafael Nov 16, 2023
63329c6
test: remove only
tapiarafael Nov 16, 2023
add7b02
Merge branch 'develop' into feat/user-panel
rique223 Nov 22, 2023
1e5943e
Merge branch 'feat/user-panel' into feat/new-users-tab-endpoints
tapiarafael Nov 22, 2023
156250f
Merge pull request #30869 from RocketChat/feat/new-users-tab-endpoints
tapiarafael Nov 28, 2023
29a50b7
feat: Implement users page deactivated tab (#30532)
rique223 Nov 29, 2023
48ac19a
Merge remote-tracking branch 'origin/develop' into feat/user-panel
hugocostadev Dec 6, 2023
ebc79c5
Merge remote-tracking branch 'origin/develop' into feat/user-panel
hugocostadev Dec 13, 2023
94f0da0
Merge branch 'develop' into feat/user-panel
hugocostadev Jan 4, 2024
5d73c9a
Merge branch 'develop' into feat/user-panel
rique223 Jan 10, 2024
fdd77a8
feat: :sparkles: Introduce new user.list endpoint to UsersTable
rique223 Jan 12, 2024
0f1204f
feat: :sparkles: Implement search by text in new users.list endpoint
rique223 Jan 12, 2024
998bca4
Merge branch 'develop' into feat/user-panel
hugocostadev Jan 15, 2024
480b392
fix: removing fields protected by permissions from API and UI
hugocostadev Jan 15, 2024
00a68da
fix: removing app user type from pending users list
hugocostadev Jan 15, 2024
7e11253
fix: IAdminUserTabs type
hugocostadev Jan 16, 2024
734d1c3
Merge remote-tracking branch 'origin/develop' into feat/user-panel
hugocostadev Jan 16, 2024
c1c9ed8
feat: implement resend email for pending users
hugocostadev Jan 16, 2024
50c853c
fix: remove TODO
hugocostadev Jan 16, 2024
26d6545
fix: remove duplicated key
hugocostadev Jan 17, 2024
c3884ea
adding more tests cases for users api
hugocostadev Jan 17, 2024
6a9bc56
feat: :sparkles: Implement role filter in new users page
rique223 Jan 17, 2024
bd60399
Merge branch 'feat/user-panel' of github.com:RocketChat/Rocket.Chat i…
rique223 Jan 17, 2024
ed3d2c6
Merge branch 'develop' into feat/user-panel
rique223 Jan 18, 2024
019321e
feat: :sparkles: Implement roles filter search bar and pending users …
rique223 Jan 18, 2024
f4019ec
refactor: :recycle: Refactor usePendingUsersCount and refactor UsersT…
rique223 Jan 18, 2024
002e0a3
Merge branch 'feat/user-panel' of github.com:RocketChat/Rocket.Chat i…
rique223 Jan 18, 2024
7b9e648
Merge branch 'develop' into feat/user-panel
hugocostadev Jan 19, 2024
b6da74c
fix: remove unused translations
hugocostadev Jan 19, 2024
a30caaa
fix: role filter name
hugocostadev Jan 19, 2024
ddf3be0
fix: updating changeset message
hugocostadev Jan 19, 2024
43b694a
refactor: :recycle: Add 'pending' to users table registration status …
rique223 Jan 19, 2024
a630043
Merge branch 'feat/user-panel' of github.com:RocketChat/Rocket.Chat i…
rique223 Jan 19, 2024
83138d6
fix: removing exceeding keys
hugocostadev Jan 19, 2024
f997dfd
fix: fixing translation order
hugocostadev Jan 19, 2024
538ec12
fix: users api tests
hugocostadev Jan 19, 2024
2a1c035
Merge branch 'develop' into feat/user-panel
rique223 Jan 19, 2024
b3bf96b
fix: users api .only()
hugocostadev Jan 19, 2024
8b1bce6
fix: remove created user counter
hugocostadev Jan 19, 2024
407e68d
fix: :bug: Uneven users table avatars
rique223 Jan 19, 2024
15ce04d
Merge branch 'feat/user-panel' of github.com:RocketChat/Rocket.Chat i…
rique223 Jan 19, 2024
8cfbcd3
Fix ci
rique223 Jan 19, 2024
492084c
fix: misc return value
hugocostadev Jan 22, 2024
3bac561
fix: change requests
hugocostadev Jan 22, 2024
03726f8
Update apps/meteor/app/api/server/v1/misc.ts
hugocostadev Jan 22, 2024
e4d2e81
fix: [/users.sendWelcomeEmail] api tests
hugocostadev Jan 22, 2024
609b53d
fix: pr change requests
hugocostadev Jan 22, 2024
505d2fc
Merge branch 'develop' into feat/user-panel
hugocostadev Jan 22, 2024
5327e96
Merge branch 'develop' into feat/user-panel
rique223 Jan 23, 2024
3ad03d4
refactor: :recycle: Change user.list/:status to users.listByStatus
rique223 Jan 23, 2024
c4d63f6
Merge branch 'feat/user-panel' of github.com:RocketChat/Rocket.Chat i…
rique223 Jan 23, 2024
50499cd
test: :white_check_mark: Add query param to wrong test
rique223 Jan 23, 2024
6cc5580
Merge branch 'develop' into feat/user-panel
casalsgh Jan 24, 2024
784e128
Update .changeset/serious-poets-smash.md
rique223 Jan 25, 2024
3f459cf
fix: adding ajv status validation, types and adapting tests cases
hugocostadev Jan 25, 2024
2d0c3c4
fix: fix typing
hugocostadev Jan 25, 2024
7996be0
Reviews
rique223 Jan 25, 2024
98dfaa1
Merge branch 'feat/user-panel' of github.com:RocketChat/Rocket.Chat i…
rique223 Jan 25, 2024
9d8800a
refactor: :recycle: Remove unnecessary params from query and improve …
rique223 Jan 25, 2024
2c64eed
refactor: :recycle: Invalidate usersPendingCount query inside of useM…
rique223 Jan 25, 2024
b80fdd9
Remove setState from inside of useQuery onSuccess
rique223 Jan 30, 2024
6a9d687
Typecheck
rique223 Jan 31, 2024
2beccf9
Merge branch 'develop' into feat/user-panel
rique223 Feb 20, 2024
0b47cda
translation-check
rique223 Feb 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/serious-poets-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@rocket.chat/meteor": minor
"@rocket.chat/rest-typings": minor
"@rocket.chat/core-typings": patch
"@rocket.chat/ui-client": patch
---

New admin user panel to manage users in different status, such as: All, Pending, Active, Deactivated
5 changes: 2 additions & 3 deletions apps/meteor/app/api/server/v1/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { passwordPolicy } from '../../../lib/server';
import { apiDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger';
import { settings } from '../../../settings/server';
import { getDefaultUserFields } from '../../../utils/server/functions/getDefaultUserFields';
import { isSMTPConfigured } from '../../../utils/server/functions/isSMTPConfigured';
import { getURL } from '../../../utils/server/getURL';
import { API } from '../api';
import { getLoggedInUser } from '../helpers/getLoggedInUser';
Expand Down Expand Up @@ -634,9 +635,7 @@ API.v1.addRoute(
{ authRequired: true },
{
async get() {
const isMailURLSet = !(process.env.MAIL_URL === 'undefined' || process.env.MAIL_URL === undefined);
const isSMTPConfigured = Boolean(settings.get('SMTP_Host')) || isMailURLSet;
return API.v1.success({ isSMTPConfigured });
return API.v1.success({ isSMTPConfigured: isSMTPConfigured() });
},
},
);
Expand Down
128 changes: 128 additions & 0 deletions apps/meteor/app/api/server/v1/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
isUserSetActiveStatusParamsPOST,
isUserDeactivateIdleParamsPOST,
isUsersInfoParamsGetProps,
isUsersListStatusProps,
isUsersSendWelcomeEmailProps,
isUserRegisterParamsPOST,
isUserLogoutParamsPOST,
isUsersListTeamsProps,
Expand All @@ -17,6 +19,7 @@ import {
isUsersCheckUsernameAvailabilityParamsGET,
isUsersSendConfirmationEmailParamsPOST,
} from '@rocket.chat/rest-typings';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import { Accounts } from 'meteor/accounts-base';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';
Expand All @@ -25,6 +28,7 @@ import type { Filter } from 'mongodb';
import { i18n } from '../../../../server/lib/i18n';
import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKey';
import { saveUserPreferences } from '../../../../server/methods/saveUserPreferences';
import { sendWelcomeEmail } from '../../../../server/methods/sendWelcomeEmail';
import { getUserForCheck, emailCheck } from '../../../2fa/server/code';
import { resetTOTP } from '../../../2fa/server/functions/resetTOTP';
import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
Expand Down Expand Up @@ -555,6 +559,130 @@ API.v1.addRoute(
},
);

API.v1.addRoute(
'users.listByStatus',
{
authRequired: true,
validateParams: isUsersListStatusProps,
permissionsRequired: ['view-d-room', 'view-outside-room'],
},
{
async get() {
const { offset, count } = await getPaginationItems(this.queryParams);
const { sort, fields } = await this.parseJsonQuery();
const { status, roles, searchTerm } = this.queryParams;

const projection = {
name: 1,
username: 1,
emails: 1,
roles: 1,
status: 1,
active: 1,
avatarETag: 1,
lastLogin: 1,
type: 1,
reason: 0,
...fields,
};

const actualSort: Record<string, 1 | -1> = sort || { username: 1 };

if (sort?.status) {
actualSort.active = sort.status;
}

if (sort?.name) {
actualSort.nameInsensitive = sort.name;
}

let match: Filter<IUser>;

switch (status) {
case 'active':
match = {
active: true,
lastLogin: { $exists: true },
};
break;
case 'all':
match = {};
break;
case 'deactivated':
match = {
active: false,
lastLogin: { $exists: true },
};
break;
case 'pending':
match = {
lastLogin: { $exists: false },
type: { $nin: ['bot', 'app'] },
};
projection.reason = 1;
break;
default:
throw new Meteor.Error('invalid-params', 'Invalid status parameter');
}

const canSeeAllUserInfo = await hasPermissionAsync(this.userId, 'view-full-other-user-info');

match = {
...match,
$or: [
...(canSeeAllUserInfo ? [{ 'emails.address': { $regex: escapeRegExp(searchTerm), $options: 'i' } }] : []),
{ username: { $regex: escapeRegExp(searchTerm), $options: 'i' } },
{ name: { $regex: escapeRegExp(searchTerm), $options: 'i' } },
],
};

if (roles?.length && !roles.includes('all')) {
match = {
...match,
roles: { $in: roles },
};
}

const { cursor, totalCount } = await Users.findPaginated(
{
...match,
},
{
sort: actualSort,
skip: offset,
limit: count,
projection,
},
);

hugocostadev marked this conversation as resolved.
Show resolved Hide resolved
const [users, total] = await Promise.all([cursor.toArray(), totalCount]);

return API.v1.success({
users,
count: users.length,
offset,
total,
});
},
},
);

API.v1.addRoute(
'users.sendWelcomeEmail',
{
authRequired: true,
validateParams: isUsersSendWelcomeEmailProps,
},
{
async post() {
const { email } = this.bodyParams;
await sendWelcomeEmail(email);

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

API.v1.addRoute(
'users.register',
{
Expand Down
6 changes: 6 additions & 0 deletions apps/meteor/app/utils/server/functions/isSMTPConfigured.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { settings } from '../../../settings/server';

export const isSMTPConfigured = (): boolean => {
const isMailURLSet = !(process.env.MAIL_URL === 'undefined' || process.env.MAIL_URL === undefined);
return Boolean(settings.get('SMTP_Host')) || isMailURLSet;
};
6 changes: 3 additions & 3 deletions apps/meteor/client/components/InfoPanel/InfoPanelTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import React from 'react';

type InfoPanelTitleProps = {
title: string;
icon: ReactNode;
icon?: ReactNode;
};

const isValidIcon = (icon: ReactNode): icon is IconName => typeof icon === 'string';

const InfoPanelTitle: FC<InfoPanelTitleProps> = ({ title, icon }) => (
<Box display='flex' flexShrink={0} alignItems='center' fontScale='h4' color='default' withTruncatedText>
<Box display='flex' flexShrink={0} alignItems='center' fontScale='p1m' color='default' withTruncatedText>
{isValidIcon(icon) ? <Icon name={icon} size='x22' /> : icon}
<Box mis={8} withTruncatedText title={title}>
<Box withTruncatedText title={title} mis={8}>
{title}
</Box>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/components/UserCard/UserCardInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ReactElement, ComponentProps } from 'react';
import React from 'react';

const UserCardInfo = (props: ComponentProps<typeof Box>): ReactElement => (
<Box mbe={8} is='span' fontScale='p2' color='hint' withTruncatedText {...props} />
<Box mb={8} is='span' fontScale='p2' color='hint' withTruncatedText {...props} />
);

export default UserCardInfo;
2 changes: 1 addition & 1 deletion apps/meteor/client/components/UserCard/UserCardRoles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import UserCardInfo from './UserCardInfo';

const UserCardRoles = ({ children }: { children: ReactNode }): ReactElement => (
<Box m='neg-x2'>
<UserCardInfo flexWrap='wrap' display='flex' flexShrink={0}>
<UserCardInfo mb={8} flexWrap='wrap' display='flex' flexShrink={0}>
rique223 marked this conversation as resolved.
Show resolved Hide resolved
{children}
</UserCardInfo>
</Box>
Expand Down
Loading
Loading